Instance method then
The then method
The state attribute of a Promise [[PromiseState]] is not exposed to the Promise object, so the state of the Promise cannot be detected programmatically, only when the state of the Promise changes, specific actions are taken through the then() method. The fulfillment function receives two parameters: the first is the function to be called when the Promise state becomes fulfilled, and the additional data associated with the asynchronous operation is passed to the fulfillment function; The second is the function that is called when the Promise state changes to Rejected, and all the additional data related to the failed state is passed to the Rejection function.
Then method source
Promise.prototype.then = function (onFulfilled, onRejected) {
if (this.constructor ! = =Promise) {
// What does current constructor do when it is not a Promise constructor
return safeThen(this, onFulfilled, onRejected)
}
// Define an empty Promise object
var res = new Promise(noop)
// Add the success handler and failure handler bindings
handle(this.new Handler(onFulfilled, onRejected, res))
// Return the promise object for the chain call to then
return res
}
function handler(onFulfilled, onRejected, promise) {
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null
this.onRejected = typeof onRejectd === 'function' ? onRejected : null
this.promise = promise
}
function handle (self, deferred) {... handleResolve(self, deferred) }function handleResolve(self, deferred) {
// Determine whether cb is set as a success function or a rejection function based on the current execution status
var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected
if (cb === null) {
if (self._state === 1) { // Execute successfully, but no success handler is passed, call resolve again for the next concatenated THEN method capture
resolve(deferred,promise, self._value)
} else {
reject(deferred,promise, self._value)
}
return
}
// The tryCallOne method penetrates the values from resolve to then
var ret = tryCallOne(cb, self._value) {
if (ret === IS_ERROR) {
reject(deferred,promise, LAST_ERROR)
} else {
resolve(deferred,promise, ret)
}
}
}
Copy the code
Then source code to achieve two function points: first, then chain call; Second, reject and resolve output values are processed into THEN.
-
Then chain call implementation, the code is as follows:
Promise.prototype.then = function (onFulfilled, onRejected) {...var res = new Promise(noop) handle(this.new Handler(onFulfilled, onRejected, res)) return res } Copy the code
First, the Promise object is re-instantiated in the then method, and the source code in the Promise Study Notes – 2 article can be seen that the noOP passed in during the instantiation is an empty function, the purpose is to make then return a Promise object. Because each Promise object must have its own then handler, the purpose of the chain call is achieved.
-
Passing a value of resolve or reject from instantiation to the then method is implemented as follows:
function tryCallOne(fn, a) { try { return fn(a) } catch (ex) { LAST_ERROR = ex return IS_ERROR } } Copy the code
Pass the success or failure handler passed in then and the current self._value to tryCallOne(). Internally, fn(a) penetrates self._value to THEN.
-
Chain calls when penetrating. Let’s start with an example
let promise = new Promise(function (resolve, reject) { resolve(2) }).then(null).then(res= > { console.log(res) / / 2 }) Copy the code
If the first THEN method fails to pass the handler, the second then house outputs the value in resolve. What is done in the handleResolve() method?
function handleResolve (self, deferred) { var cb = self._state === 1 ? deferred.onFulfilled ? deferred.onRejected if (cb === null) { if (self._state === 1) { resolve(deferred.promise, self._value) } else { reject(deferred.promise, self._value) } return}}Copy the code
Resolve() is called again, and return (self._state = 1) when the first then null is passed to handleResolve(). The var res = new Promise(noOP) instance adds the resolve method, which is then processed by the second then method and results in 2.
Instance method catch
The catch() method is equivalent to the then() method that only passes it a rejection handler. So its implementation calls the then() method on the instance. The source code is as follows:
Promise.prototype['catch'] = function (onRejected) {
return this.then(null, onRejected)
}
Copy the code
Instance method finally
The function of the finally method
The finally() method is used to specify actions that will be performed regardless of the state of the Promise object. The callback function in finally() does not accept any parameters, which means there is no way to know whether the Promise state is a pity or rejected. This indicates that operations in finally do not depend on the execution result of a Promise.
The finally usage
The server uses Promise to process the request, and then uses Finally to shut down the server
server.listen(port).then(function () {... }).finally(server.stop)Copy the code
Finally method source
Finally () is essentially a special case of the then method. The implementation process is as follows:
Promise.prototype.finally = function (f) {
return this.then(function (value) {
return Promise.resolve(f ()).then(function () {
return value
})
}, function (reason) {
return Promise.resolve(f ()).then(function () {
throw reason
})
})
}
Copy the code
The resources
ECMAScript 6 Getting Started -Promise objects