preface
Baidu many times others write promise, but also on a whim today I wrote one and made such a record
Promises/A+
Class: Look up Promises/A+ here
Just do it
Then I look at the norm according to my own habits
-
“Promise” is an object or function with a then method whose behavior conforms to this specification.
Class Promise{} and function Promise{}
class Promise{
constructor(execuctor) {}
}
export default Promise
Copy the code
-
A promise must be in one of three states: pending, fulfilled, or rejected….
This is very depressing. Each promise has three states, which can be changed (through resolve and reject), or rejected, but can only be changed once and cannot be changed to any other state.
-
“Reason” is a value that indicates why a promise was rejected.
“Value” is any legal JavaScript value (including undefined, a thenable, or a promise).
The initialization of the resolve() and reject() parameters and their values, combined with 2, does state change processing
Const PENDING = "PENDING"; const PENDING = "PENDING"; const PENDING = "PENDING"; /** ** ** ** ** * / / const REJECTED = "REJECTED"; class Promise{ constructor(execuctor) { this.status = PENDING; this.value = undefined; this.reason = undefined; Const resolve = (val) => {if (this.status === PENDING) {this.value = val; This. Status = FULFILLED; // this. // Modify the state}}; If (this.status === PENDING) {this.reason = err; const reject = (err) => {reject = (err); // This. Status = REJECTED; // This. // Modify the state}}}Copy the code
-
“Exception” is a value that is thrown using the throw statement.
An exception thrown by a throw statement. So in my own way I’m using try,catch and I’m calling reject(err)
try {
execuctor(resolve, reject);
} catch (err) {
reject(err);
}
Copy the code
-
A promise’s then method accept two arguments: promise. Then (onFulfilled, onRejected)….
This will be FULFILLED FULFILLED, this will be FULFILLED, this will be FULFILLED, this will be FULFILLED, this will be FULFILLED, this will be FULFILLED, this will be FULFILLED
then(onFulfilled, onRejected) {
if (this.status === FULFILLED) {
onFulfilled(this.value);
}
if (this.status === REJECTED) {
onRejected(this.reason);
}
Copy the code
If the setTimeout package resolve is delayed, then the status will always be pending and the corresponding function will not be executed
- 🌰
let promise = new Promise((resolve, reject) => { console.log("promise begin"); SetTimeout (() => {resolve(" success "); }, 1000); }); Promise.then (// can't print, because the timer was executed before then so the state in then is always pending (res) => {console.log(res); }, (err) => { console.log(err); });Copy the code
- Solution: Cache the callback function in the then array and publish it in conjunction with the publish/subscribe pattern
Constructor () {/ / cache the constructor add two arrays do this. OnFulfilledCallback = [] this. OnRejectedCallback = []} / / modify then implement, enforce then Do onFulfilled, onRejected, push into the cache array operation then (onFulfilled, onRejected) { if (this.status === PENDING) { this.onFulfilledCallback.push(() => { onFulfilled(this.value); }); this.onRejectedCallback.push(() => { onRejected(this.reason); }); }} / / resolve method in new traversal onFulfilledCallback array and perform this. OnFulfilledCallback. ForEach (fn = > fn ()) / / reject method in the same way this.onRejectedCallback.forEach(fn=>fn())Copy the code
- Re-execute the setTimeout example above to print normally
-
then may be called multiple times on the same promise…..
then must return a promise
promise2 = promise1.then(onFulfilled, onRejected); .
Dish 🐔 own translation:
- The THEN method returns a PROMISE object for chained calls
This is a pity pity. This is a pity pity. Let promise2 = new promise ((fulfilled, fulfilled, fulfilled)). reject) => { if (this.status === PENDING){... }}}Copy the code
- The state received in the THEN is the success or failure state of the previous THEN
- The success callback is called on success and the failure callback is called on failure..
- The result of the previous THEN, x, is used as an incoming argument to resolve() and reject() for the entire promise of the current return
// The status of the previous THEN is received in the new THEN, This is very sad. This is very sad. This is very sad. This is very sad This is very depressing. Reject if (this.status === FULFILLED) {try {let x = onFulfilled(this.value); resolve(x); } catch (err) { reject(err); }} if (this.status === REJECTED) {try {let x = onRejected(this.reason);}} if (this.status === REJECTED) {try {let x = onRejected(this.reason); resolve(x); } catch (err) { reject(err); } // If (this.status === PENDING);} // If (this.status === PENDING)Copy the code
The complete code
class Promise { constructor(execuctor) { this.status = PENDING; this.value = undefined; this.reason = undefined; Const resolve = (val) => {if (this.status === PENDING) {this.value = val; This. Status = FULFILLED; // this. // Modify the state}}; If (this.status === PENDING) {this.reason = err; const reject = (err) => {reject = (err); // This. Status = REJECTED; // This. // Modify the state}}; try { execuctor(resolve, reject); } catch (err) { reject(err); Let promise2 = new Promise((resolve, reject) => {//2. This is very sad. This is very sad. If (this. Status === FULFILLED) {// 4. This is very depressing. This is very depressing. This is very depressing. Reject resolve(x); reject resolve(x); reject resolve(x); reject resolve(x); } catch (err) { reject(err); }} if (this.status === REJECTED) {try {let x = onRejected(this.reason);}} if (this.status === REJECTED) {let x = onRejected(this.reason); Reject resolve(x) : reject resolve(x); reject resolve(x) : reject resolve(x); } catch (err) { reject(err); } // make a subscription //then take the resolve function and reject function // 3. In order to support the chain calls for the first time, then will the execution result x to the corresponding resolve or reject the if (this. The status = = = PENDING) {/ / asynchronous calls this. OnFulfilledCallback. Push (() = > { try { let x = onFulfilled(this.value); resolve(x); } catch (err) { reject(err); }}); this.onRejectedCallback.push(() => { try { let x = onRejected(this.reason); resolve(x); } catch (err) { reject(err); }}); }}); return promise2; } export default PromiseCopy the code
The code test plugin uses Code Run.
summary
This is the end of the code for a simple then chaining call to a Promise. Let’s continue next time when x returns a promise object to handle