Skip to content

Commit

Permalink
Adding XHR support
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewp committed Nov 16, 2015
1 parent 9beab3a commit 2138c27
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 37 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules/
3 changes: 3 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
test/
demo.html
demo.js
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ For can-wait to work we have to override various task-creating functionality, th
**Macrotasks**

* setTimeout
* XMLHttpRequest

**Microtasks**

Expand Down
95 changes: 63 additions & 32 deletions can-wait.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ function Deferred(){
});
}

var waitWithinRequest = g.canWait = function(fn){
var request = waitWithinRequest.currentRequest;
request.waits++;

return function(){
return request.run(fn, this, arguments);
};
};

function Override(obj, name, fn) {
this.old = obj[name];
this.obj = obj;
Expand All @@ -27,80 +36,102 @@ Override.prototype.release = function(){
this.obj[this.name] = this.old;
};

var overrideSetTimeout = function(overrides){
var overrideSetTimeout = function(request){
return new Override(g, "setTimeout", function(setTimeout){
return function(fn, timeout){
var dfd = new Deferred();
overrides.promises.push(dfd.promise);

return setTimeout.call(this, function(){
return overrides.run(fn, dfd);
}, timeout);
var callback = waitWithinRequest(fn);
return setTimeout.call(this, callback, timeout);
}
});
};

var overrideRAF = function(overrides){
var overrideRAF = function(request){
return new Override(g, "requestAnimationFrame", function(rAF){
return function(fn){
var dfd = new Deferred();
overrides.promises.push(dfd.promise);
var callback = waitWithinRequest(fn);
return rAF.call(this, callback);
};
});
};

return rAF.call(this, function(){
return overrides.run(fn, dfd);
var overrideXHR = function(request){
return new Override(XMLHttpRequest.prototype, "send", function(send){
return function(){
var onreadystatechange = this.onreadystatechange,
onload = this.onload,
onerror = this.onerror,
error;

var request = waitWithinRequest.currentRequest;
var callback = waitWithinRequest(function(){
if(this.readyState === 4) {
onreadystatechange && onreadystatechange.apply(this, arguments);

if(error)
onerror && onerror.apply(this, arguments);
else
onload && onload.apply(this, arguments);
} else {
request.waits++;
}
});
this.onreadystatechange = callback;
this.onerror = function(err){ error = err };

return send.apply(this, arguments);
};
});
};

function OverrideCollection() {
function Request() {
this.deferred = new Deferred();
this.promises = [];
this.waits = 0;
var o = this.overrides = [];

o.push(overrideSetTimeout(this));
o.push(overrideRAF(this));
o.push(overrideXHR(this));
}

OverrideCollection.prototype.trap = function(){
Request.prototype.trap = function(){
var o = this.overrides;
for(var i = 0, len = o.length; i < len; i++) {
o[i].trap();
}
};

OverrideCollection.prototype.release = function(){
Request.prototype.release = function(){
var o = this.overrides;
for(var i = 0, len = o.length; i < len; i++) {
o[i].release();
}
};

OverrideCollection.prototype.run = function(fn, dfd){
Request.prototype.run = function(fn, ctx, args){
var res = this.runWithinScope(fn, ctx, args);
this.waits--;
if(this.waits === 0) {
this.deferred.resolve();
}
return res;
};

Request.prototype.runWithinScope = function(fn, ctx, args){
waitWithinRequest.currentRequest = this;
this.trap();
var res = fn();
var res = fn.apply(ctx, args);
this.release();
if(dfd)
dfd.resolve();
return res;
};

function canWait(fn) {
var overrides = new OverrideCollection();
var request = new Request();

// Call the function
overrides.run(fn);
request.runWithinScope(fn);

function waitOnAll() {
var promises = overrides.promises;
if(promises.length) {
var waiting = [].slice.call(promises);
promises.length = 0;

return Promise.all(waiting).then(waitOnAll);
}
return Promise.resolve();
}
return waitOnAll();
return request.deferred.promise;
}

if(typeof module !== "undefined" && module.exports) {
Expand Down
3 changes: 1 addition & 2 deletions demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
<tbody>
</tbody>
</table>
<script src="can-wait.js"></script>
<script src="demo.js"></script>
<script src="node_modules/steal/steal.js" main="can-wait/demo"></script>
</body>
</html>
3 changes: 2 additions & 1 deletion demo.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
var canWait = require("can-wait");

var results = [];

var requests = [
Expand Down Expand Up @@ -35,7 +37,6 @@ var requests = [
setTimeout(function(){
results.push("2-c");
});

},

function(results) {
Expand Down
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "can-wait",
"version": "0.0.1",
"description": "Asynchronous render for all frameworks",
"main": "wait.js",
"main": "can-wait.js",
"scripts": {
"test": "node test/test.js"
},
Expand All @@ -22,5 +22,8 @@
"bugs": {
"url": "https://github.com/canjs/can-wait/issues"
},
"homepage": "https://github.com/canjs/can-wait#readme"
"homepage": "https://github.com/canjs/can-wait#readme",
"devDependencies": {
"steal": "^0.12.4"
}
}

0 comments on commit 2138c27

Please sign in to comment.