Commit ec8dce36 authored by Yehuda Katz's avatar Yehuda Katz

Add RSVP.configure('onerror')

This function is invoked when an unhandled exception is thrown.
parent da484cfd
...@@ -38,6 +38,9 @@ define("rsvp/all", ...@@ -38,6 +38,9 @@ define("rsvp/all",
var Promise = __dependency1__.Promise; var Promise = __dependency1__.Promise;
function all(promises) { function all(promises) {
if(toString.call(promises) !== "[object Array]") {
throw new TypeError('You must pass an array to all.');
}
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
var results = [], remaining = promises.length, var results = [], remaining = promises.length,
promise; promise;
...@@ -318,7 +321,51 @@ define("rsvp/hash", ...@@ -318,7 +321,51 @@ define("rsvp/hash",
__exports__.hash = hash; __exports__.hash = hash;
}); });
define("rsvp/node",
["rsvp/promise","rsvp/all","exports"],
function(__dependency1__, __dependency2__, __exports__) {
"use strict";
var Promise = __dependency1__.Promise;
var all = __dependency2__.all;
function makeNodeCallbackFor(resolve, reject) {
return function (error, value) {
if (error) {
reject(error);
} else if (arguments.length > 2) {
resolve(Array.prototype.slice.call(arguments, 1));
} else {
resolve(value);
}
};
}
function denodeify(nodeFunc) {
return function() {
var nodeArgs = Array.prototype.slice.call(arguments), resolve, reject;
var thisArg = this;
var promise = new Promise(function(nodeResolve, nodeReject) {
resolve = nodeResolve;
reject = nodeReject;
});
all(nodeArgs).then(function(nodeArgs) {
nodeArgs.push(makeNodeCallbackFor(resolve, reject));
try {
nodeFunc.apply(thisArg, nodeArgs);
} catch(e) {
reject(e);
}
});
return promise;
};
}
__exports__.denodeify = denodeify;
});
define("rsvp/promise", define("rsvp/promise",
["rsvp/config","rsvp/events","exports"], ["rsvp/config","rsvp/events","exports"],
...@@ -367,6 +414,8 @@ define("rsvp/promise", ...@@ -367,6 +414,8 @@ define("rsvp/promise",
this.trigger('error', { detail: event.detail }); this.trigger('error', { detail: event.detail });
}, this); }, this);
this.on('error', onerror);
try { try {
resolver(resolvePromise, rejectPromise); resolver(resolvePromise, rejectPromise);
} catch(e) { } catch(e) {
...@@ -374,6 +423,12 @@ define("rsvp/promise", ...@@ -374,6 +423,12 @@ define("rsvp/promise",
} }
}; };
function onerror(event) {
if (config.onerror) {
config.onerror(event.detail);
}
}
var invokeCallback = function(type, promise, callback, event) { var invokeCallback = function(type, promise, callback, event) {
var hasCallback = isFunction(callback), var hasCallback = isFunction(callback),
value, error, succeeded, failed; value, error, succeeded, failed;
...@@ -408,6 +463,8 @@ define("rsvp/promise", ...@@ -408,6 +463,8 @@ define("rsvp/promise",
constructor: Promise, constructor: Promise,
then: function(done, fail) { then: function(done, fail) {
this.off('error', onerror);
var thenPromise = new Promise(function() {}); var thenPromise = new Promise(function() {});
if (this.isFulfilled) { if (this.isFulfilled) {
......
This diff is collapsed.
...@@ -5,6 +5,9 @@ define( ...@@ -5,6 +5,9 @@ define(
var Promise = __dependency1__.Promise; var Promise = __dependency1__.Promise;
function all(promises) { function all(promises) {
if(toString.call(promises) !== "[object Array]") {
throw new TypeError('You must pass an array to all.');
}
return new Promise(function(resolve, reject) { return new Promise(function(resolve, reject) {
var results = [], remaining = promises.length, var results = [], remaining = promises.length,
promise; promise;
......
define(
["rsvp/promise","rsvp/all","exports"],
function(__dependency1__, __dependency2__, __exports__) {
"use strict";
var Promise = __dependency1__.Promise;
var all = __dependency2__.all;
function makeNodeCallbackFor(resolve, reject) {
return function (error, value) {
if (error) {
reject(error);
} else if (arguments.length > 2) {
resolve(Array.prototype.slice.call(arguments, 1));
} else {
resolve(value);
}
};
}
function denodeify(nodeFunc) {
return function() {
var nodeArgs = Array.prototype.slice.call(arguments), resolve, reject;
var thisArg = this;
var promise = new Promise(function(nodeResolve, nodeReject) {
resolve = nodeResolve;
reject = nodeReject;
});
all(nodeArgs).then(function(nodeArgs) {
nodeArgs.push(makeNodeCallbackFor(resolve, reject));
try {
nodeFunc.apply(thisArg, nodeArgs);
} catch(e) {
reject(e);
}
});
return promise;
};
}
__exports__.denodeify = denodeify;
});
...@@ -45,6 +45,8 @@ define( ...@@ -45,6 +45,8 @@ define(
this.trigger('error', { detail: event.detail }); this.trigger('error', { detail: event.detail });
}, this); }, this);
this.on('error', onerror);
try { try {
resolver(resolvePromise, rejectPromise); resolver(resolvePromise, rejectPromise);
} catch(e) { } catch(e) {
...@@ -52,6 +54,12 @@ define( ...@@ -52,6 +54,12 @@ define(
} }
}; };
function onerror(event) {
if (config.onerror) {
config.onerror(event.detail);
}
}
var invokeCallback = function(type, promise, callback, event) { var invokeCallback = function(type, promise, callback, event) {
var hasCallback = isFunction(callback), var hasCallback = isFunction(callback),
value, error, succeeded, failed; value, error, succeeded, failed;
...@@ -86,6 +94,8 @@ define( ...@@ -86,6 +94,8 @@ define(
constructor: Promise, constructor: Promise,
then: function(done, fail) { then: function(done, fail) {
this.off('error', onerror);
var thenPromise = new Promise(function() {}); var thenPromise = new Promise(function() {});
if (this.isFulfilled) { if (this.isFulfilled) {
......
...@@ -41,6 +41,8 @@ var Promise = function(resolver) { ...@@ -41,6 +41,8 @@ var Promise = function(resolver) {
this.trigger('error', { detail: event.detail }); this.trigger('error', { detail: event.detail });
}, this); }, this);
this.on('error', onerror);
try { try {
resolver(resolvePromise, rejectPromise); resolver(resolvePromise, rejectPromise);
} catch(e) { } catch(e) {
...@@ -48,6 +50,12 @@ var Promise = function(resolver) { ...@@ -48,6 +50,12 @@ var Promise = function(resolver) {
} }
}; };
function onerror(event) {
if (config.onerror) {
config.onerror(event.detail);
}
}
var invokeCallback = function(type, promise, callback, event) { var invokeCallback = function(type, promise, callback, event) {
var hasCallback = isFunction(callback), var hasCallback = isFunction(callback),
value, error, succeeded, failed; value, error, succeeded, failed;
...@@ -82,6 +90,8 @@ Promise.prototype = { ...@@ -82,6 +90,8 @@ Promise.prototype = {
constructor: Promise, constructor: Promise,
then: function(done, fail) { then: function(done, fail) {
this.off('error', onerror);
var thenPromise = new Promise(function() {}); var thenPromise = new Promise(function() {});
if (this.isFulfilled) { if (this.isFulfilled) {
......
...@@ -622,6 +622,44 @@ describe("RSVP extensions", function() { ...@@ -622,6 +622,44 @@ describe("RSVP extensions", function() {
}); });
}); });
describe("RSVP.onerror", function(){
var onerror;
after(function() {
RSVP.configure('onerror', null);
});
it("When provided, any unhandled exceptions are sent to it", function(done) {
var thrownError = new Error();
RSVP.configure('onerror', function(error) {
assert.equal(error, thrownError, "The thrown error is passed in");
done();
});
new RSVP.Promise(function(resolve, reject) {
reject(thrownError);
}).then(function() {
// doesn't get here
});
});
it("When provided, handled exceptions are not sent to it", function(done) {
var thrownError = new Error();
RSVP.configure('onerror', function(error) {
assert(false, "Should not get here");
});
new RSVP.Promise(function(resolve, reject) {
reject(thrownError);
}).then(null, function(error) {
assert.equal(error, thrownError, "The handler should handle the error");
done();
});
});
});
describe("RSVP.resolve", function(){ describe("RSVP.resolve", function(){
specify("it should exist", function(){ specify("it should exist", function(){
assert(RSVP.resolve); assert(RSVP.resolve);
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment