in jones-promises/lib/Promise.js [132:208]
Promise.prototype.then = function(fulfilled_callback, rejected_callback, progress_callback) {
var self = this;
// create a new promise to return from the "then" method
var new_promise = new Promise();
if (typeof self.fulfilled_callbacks === 'undefined') {
self.fulfilled_callbacks = [];
self.rejected_callbacks = [];
self.progress_callbacks = [];
}
if (self.resolved) {
var resolved_result;
if(udebug.is_detail()) { udebug.log(this.name, 'Promise.then resolved; err:', self.err); }
if (self.err) {
// this promise was already rejected
if(udebug.is_detail()) { udebug.log(self.name, 'Promise.then resolved calling (delayed) rejected_callback', rejected_callback); }
global.setImmediate(function() {
if(udebug.is_detail()) { udebug.log(self.name, 'Promise.then resolved calling rejected_callback', fulfilled_callback); }
thenPromiseFulfilledOrRejected(self, rejected_callback, new_promise, self.err, true);
});
} else {
// this promise was already fulfilled, possibly with a null or undefined result
if(udebug.is_detail()) { udebug.log(self.name, 'Promise.then resolved calling (delayed) fulfilled_callback', fulfilled_callback); }
global.setImmediate(function() {
if(udebug.is_detail()) { udebug.log(self.name, 'Promise.then resolved calling fulfilled_callback', fulfilled_callback); }
thenPromiseFulfilledOrRejected(self, fulfilled_callback, new_promise, self.result);
});
}
return new_promise;
}
// create a closure for each fulfilled_callback
// the closure is a function that when called, calls setImmediate to call the fulfilled_callback with the result
if (typeof fulfilled_callback === 'function') {
if(udebug.is_detail()) { udebug.log(self.name, 'Promise.then with fulfilled_callback', fulfilled_callback); }
// the following function closes (this, fulfilled_callback, new_promise)
// and is called asynchronously when this promise is fulfilled
this.fulfilled_callbacks.push(function(result) {
global.setImmediate(function() {
thenPromiseFulfilledOrRejected(self, fulfilled_callback, new_promise, result);
});
});
} else {
if(udebug.is_detail()) { udebug.log(self.name, 'Promise.then with no fulfilled_callback'); }
// create a dummy function for a missing fulfilled callback per 2.2.7.3
// If onFulfilled is not a function and promise1 is fulfilled, promise2 must be fulfilled with the same value.
this.fulfilled_callbacks.push(function(result) {
global.setImmediate(function() {
thenPromiseFulfilledOrRejected(self, emptyFulfilledCallback, new_promise, result);
});
});
}
// create a closure for each rejected_callback
// the closure is a function that when called, calls setImmediate to call the rejected_callback with the error
if (typeof rejected_callback === 'function') {
if(udebug.is_detail()) { udebug.log(self.name, 'Promise.then with rejected_callback', rejected_callback); }
this.rejected_callbacks.push(function(err) {
global.setImmediate(function() {
thenPromiseFulfilledOrRejected(self, rejected_callback, new_promise, err);
});
});
} else {
if(udebug.is_detail()) { udebug.log(self.name, 'Promise.then with no rejected_callback'); }
// create a dummy function for a missing rejected callback per 2.2.7.4
// If onRejected is not a function and promise1 is rejected, promise2 must be rejected with the same reason.
this.rejected_callbacks.push(function(err) {
global.setImmediate(function() {
thenPromiseFulfilledOrRejected(self, emptyRejectedCallback, new_promise, err);
});
});
}
// todo: progress_callbacks
if (typeof progress_callback === 'function') {
this.progress_callbacks.push(progress_callback);
}
return new_promise;
};