Promise A + learning
Js itself is designed to be asynchronous, so this puts forward a requirement for coding, how to elegantly write asynchronous CODE in JS code, in the early days, we use callback to deal with this problem. But it also creates the problem of callback hell.
Then came promises, which revolutionized the way asynchronous code was written. Promise has a profound influence. It can be said that ES6 adds Promise, and yield and Generator in KOA also cooperate with Promise to realize functions like await and async. Know that true async and await in ES7 are also Promise based implementations (async and await are just syntactic sugar for Generator). Promise has become ubiquitous in asynchronous programming.
So it’s important to understand the Promise specification. Of course, it is best to look at the original text of the specification.
A+ A+ A+
Promises/A+ : Promises/A+ : Promises/A+ : Promises/A+ : Promises/A+ : Promises/A+ : Promises/A+
An open, robust, and universal JavaScript Promise standard. Developed by developers for their reference.
A Promise represents the end result of an asynchronous operation and interacts with it primarily through the then method, which registers two callback functions to receive the end value of a Promise or the reason why the Promise cannot be implemented.
This specification details the implementation process of THEN. Promises/A+ can be used as A reference to implement THEN. This specification is therefore very stable. Although the Promise/A+ organization may revise the specification from time to time, it is primarily to address specific boundary cases, and these changes are minor and backward compatible. If we were to make a large-scale incompatible update, we would have thought carefully, discussed exhaustively, and tested rigorously in advance.
Historically, this specification has explicitly defined the recommendations of the previous Promise/A specification as A standard of behavior: we extend the established behavior of the original specification while eliminating some exceptions and problematic aspects of the original specification.
Finally, the core Promises/A+ specification does not design how to create, resolve, and reject Promises. Instead, it focuses on providing A universal then approach. The above approach to Promises may be mentioned in other codes in the future.
The term
1.1 Promise
A promise is an object or function with a then method that behaves in accordance with this specification;
1.2 thenable
Is an object or function that defines a THEN method.
1.3 Value
Any JavaScript legal value (including undefined, thenable, and promise);
1.4 Exceptions
Is a value thrown using the throw statement.
1.5 Reason
Indicate a reason for rejecting a promise.
requirements
2.1 State of Promise
The current state of a Promise must be one of the following three states: Pending, Fulfilled and Rejected.
2.1.1 Pending
In the wait state, the promise must meet the following conditions:
- You can migrate to the execute or reject state
2.1.2 Execution state (depressing)
In the execution state, a promise must satisfy the following conditions:
- You cannot migrate to any other state
- You must have an immutable end value
2.1.3 Rejected State (Rejected)
In the rejection state, a promise must satisfy the following conditions:
- You cannot migrate to any other state
- There must be an immutable cause
Immutability here refers to identity (equality can be determined by ===), not to a deeper immutability
2.2 then
methods
A promise must provide a THEN method to access its current value, final value, and reason
Promise’s then method accepts two arguments:
promise.then(onFulfilled, onRejected)
Copy the code
2.2.1 onFulfilled
和 onRejected
Both are optional parameters.
2.2.1.1 ifonFulfilled
Is not a function, which must be ignored
2.2.1.2 ifonRejected
Is not a function, which must be ignored
2.2.2 ifonFulfilled
Is the function:
2.2.2.1 whenpromise
It must be called after execution, and its first argument ispromise
The final value
Similar onFulfilled (value);
2.2.2.2 inpromise
It cannot be called until execution ends
// onFulfilled is a pseudo-code, which represents the implementation function of onFulfilled: var onFulfilled =function() {
console.log("onFulfilled");
}
var c = new Promise((onFulfilled, onRejected) => {
onFulfilled('ok');
console.log('123');
})
> '123'
> 'onFulfilled'
Copy the code
2.2.2.3 It cannot be invoked more than once
var c = new Promise((onFulfilled, onRejected) => {
onFulfilled('ok');
onFulfilled('ok2');
});
c.then((data) => {
console.log(data); // 'ok'
})
Copy the code
2.2.3 ifonRejected
Is the function:
2.2.3.1 whenpromise
It must be called if execution is rejected, and its first argument ispromise
According to the for
2.2.3.2 inpromise
It cannot be called until execution is rejected
2.2.3.3 It cannot be invoked more than once
2.2.4 onFulfilled
andonRejected
Can only be called if the execution environment stack contains only platform code
2.2.5 OnFulfilled and onRejected must be called as functions (i.e. without this).
2.2.6 The then method can be called multiple times by the same Promise
2.2.6.1 When the promise is successfully implemented, all ondepressing shall be called back successively according to its registration order
2.2.6.1 When the Promise is rejected, all onRejected should be called back according to its registration order
2.2.7 Then must return onepromise
promise2 = promise1.then(onFulfilled, onRejected);
Copy the code
2.2.7.1 If Ondepressing oronRejected
Return a value x, then run the following Promise resolution: [[Resolve]](promise2, x)
2.2.7.2 If Ondepressing oronRejected
If an exception e is thrown, promise2 must reject execution and return reject cause E
2.2.7.3 If ondepressing is not a function and promise1 performs successfully, promise2 must perform successfully and return the same value
2.2.7.4 ifonRejected
If it is not a function and promise1 rejects execution, promise2 must reject execution and return the same data
2.3 Promise settlement process
Promise.then() will return a new Promise, but it will return the value of the return function of the promise.then (). Take another look at 2.2.7 above
Promise resolution is an abstract operation that takes a Promise and a value, which we express as [[Resolve]](Promise, x). If x has a then method and looks like a Promise, The resolver attempts to make the Promise accept x’s state; Otherwise it implements the promise with the value of x.
This thenable feature makes Promise implementation more universal: as long as it exposes A THEN method that follows the Promise/A+ protocol; This also allows implementations that follow the Promise/A+ specification to coexist well with less formal but usable implementations.
To run [[Resolve]](promise, x), follow these steps:
2.3.1 X equals Promise
If a promise and x point to the same object, reject the promise as TypeError grounds
var p = new Promise(function(resolve, reject) { resolve(123); }); / *then*/ var p2 = p.hen ((data) => {/ var p2 = p.hen ((data) => {return p2;
});
>> Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise>
Copy the code
2.3.2 x for the Promise
If x is a Promise, make the Promise accept the state of X
2.3.2.1 If X is in wait state, the promise must remain in wait state until X is implemented or rejected
2.3.2.2 If x is in the execution state, execute the promise with the same value
2.3.2.3 If X is in the reject state, reject the promise with the same data reason
This is actually a feature that we use a lot, which I won’t explain here, which is the promise chain call
getUserInfo().then((userInfo) => {
return getCompanyInfo();
}).then((companyInfo) => {
return getCityInfo();
}).then((cityInfo) => {
})
Copy the code
2.3.3 X is an object or function
2.3.3.1 Assign x. teng to THEN
Create a new variable then, like var then = x.teng; , the effect is actually similar to our usual way of doing so, convenient for later use.
2.3.3.2 If an error e is thrown when the value of x. teng is set, the promise is rejected based on E
function objFactory() {
var obj = {};
Object.defineProperty(obj, "then", {
get: function() {
throw Error('then error'); }});return obj;
}
var a = new Promise((resolve) => {
resolve();
});
a.then(() => {
return objFactory()
});
// Uncaught (in promise) Error: then error
Copy the code
2.3.3.3 If then is a function, x is called as the function’s scope this. Pass two callback functions as arguments, the first called resolvePromise and the second called rejectPromise:
// Similar to this code varthen = x.then;
if (typeof then= = ='function') {
then.call(x, resolvePromise, rejectPromise);
}
Copy the code
2.3.3.3.1 If resolvePromise is called with a value y, run [[Resolve]](promise, y)
function objFactory() {
var obj = {};
Object.defineProperty(obj, "then", {
get: function() {
return function(resolvePromise, rejectPromise) {
resolvePromise('resolve_y'); }}});return obj;
}
var a = new Promise((resolve) => {
resolve();
});
var c = a.then(() => {
return objFactory()
});
c.then((data) => {
console.log(data); // "resolve_y"
})
Copy the code
2.3.3.3.2 If rejectPromise is invoked with r, reject the promise with r
A similar 2.3.3.3.1 / /function objFactory() {
var obj = {};
Object.defineProperty(obj, "then", {
get: function() {
return function(resolvePromise, rejectPromise) {
rejectPromise('resolve_y'); }}});return obj;
}
Copy the code
2.3.3.3.3 If both resolvePromise and rejectPromise are invoked, or if the same parameter is invoked more than once, the first invocation is preferred and the remaining calls are ignored
I’m not going to give you an example, but it’s pretty straightforward
2.3.3.3.4 If calling the THEN method raises exception E:
2.3.3.3.4.1 If resolvePromise or rejectPromise has already been invoked, ignore it
function objFactory() {
var obj = {};
Object.defineProperty(obj, "then", {
get: function() {
return function(resolvePromise, rejectPromise) {
resolvePromise('resolve_y');
console.log(test); }}});return obj;
}
var a = new Promise((resolve) => {
resolve();
});
var c = a.then(() => {
return objFactory()
});
c.then((data) => {
console.log(data); // "resolve_y"
})
Copy the code
2.3.3.3.4.2 Otherwise reject promise based on E
function objFactory() {
var obj = {};
Object.defineProperty(obj, "then", {
get: function() {
return function(resolvePromise, rejectPromise) {
console.log(test);
resolvePromise('resolve_y'); }}});return obj;
}
var a = new Promise((resolve) => {
resolve();
});
var c = a.then(() => {
return objFactory()
});
// VM1124:6 Uncaught (in promise) ReferenceError: test is not defined
Copy the code
2.3.3.3.5 If THEN is not a function, execute a promise with an x argument
function objFactory() {
var obj = {};
Object.defineProperty(obj, "then", {
get: function() {
return 'test'; }});return obj;
}
var a = new Promise((resolve) => {
resolve();
});
var c = a.then(() => {
return objFactory()
});
c.then((data) => {
console.log(data); // object {then: "test"}})Copy the code
2.3.3.4 If x is not an object or function, execute a promise with x as an argument
var a = new Promise((resolve) => {
resolve();
});
var c = a.then(() => {
return "test"
});
c.then((data) => {
console.log(data); // "test"
})
Copy the code
To be continued