Write at the beginning: The first time I write this kind of note, the reason why I choose a bad Promise is because it is often used. If you see any mistakes, please correct them. If you bring the cute new to the ditch, you will climb out of it.
Unpack the use of promises:
- When using a Promise, you create a Promise object with a new keyword;
new Promise();
Copy the code
Once created, you can see that the Promise is a class (MDN reference: developer.mozilla.org/zh-CN/docs/…).
- When executing this class, you need to pass in a callback function that executes immediately (see figure below). This means that the callback will be executed immediately after a Promise is created (which seems like nonsense).
new Promise(() => {});
Copy the code
- When you use a Promise, you pass two arguments: resolve, reject; Calling these two parameters changes the state of the Promise, so these two parameters are actually two functions.
new Promise((resolve, reject) => {});
Copy the code
- State of a Promise: pending; Failure rejected; Successfully fulfilled;
New Promise(() => {resolve(' succeed '); // reject(' reject '); }); // The state will be changed to success: pending -> pity // Reject: pending -> RejectCopy the code
Resolve is a success, reject is a failure, and vice versa. I think so! But the turtle’s ass — rules!
- You can also assign the result of a Promise execution to a variable when you use a Promise. You can also call the Promise method then; The then method determines the current state of the Promise and calls a successful callback if it succeeds and a failed callback if it fails
Let promise = new promise (() => {resolve(' succeed '); // reject(' reject '); }); // Call Promise's method then; Then (() => {}, () => {});Copy the code
- A successful callback to the then method takes one parameter, indicating the value of the success, and one parameter, indicating the reason for the failure
Let promise = new promise (() => {resolve(' succeed '); // reject(' reject '); }); // Call Promise's method then; Promise. then(value => {}, reason => {});Copy the code
The breakdown analysis ends and a Promise is implemented
- Since Promise is a class, create one using the class keyword
class myPromise {}
Copy the code
- The callback function needs to be passed in when the class executes, so the callback function is received via the constructor.
class myPromise { constructor(executor) { executor(); }}Copy the code
- Resolve and reject are also passed in when the callback is called
class myPromise { constructor(executor) { executor(this.resolve, this.reject); } // Q: why arrow function? A1: These two functions are called directly. If the two functions are a normal function, this refers to window or undefined. Resolve = () => {}; resolve = () => {}; reject = () => {}; }Copy the code
- You need to change the state of the Promise to succeed when you call resolve, and to fail when you call Reject.
// Change the state to have a state (truth!) const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'reiected'; // Q: Why constant? // class myPromise {constructor(executor) {executor(this.resolve, this.reject); } // Since this state is unique to each Promise, we define it as an instance property status = PENDING; Resolve = () => {// This. Status = big; }; Reject = () => {// Reject status = REJECTED; }; }Copy the code
PS: Why is’ resolve ‘a success,’ reject ‘a success? You can’t decide what you wrote? Line! You can! No problem! Just write a program and have fun.
- Promise state once the change will not be able to change again, according to the above method calls the callback after the success and then calls the callback failure, so the success and failure, so this implementation is problems (white to write there is a problem in a pile, it is to write a lonely ah) in order to prevent it from repeated horizontal jump between success and failure, Give it a try when changing the state
const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'reiected'; class myPromise { constructor(executor) { executor(this.resolve, this.reject); } status = PENDING; resolve = () => { if (this.status ! == PENDING) return; this.status = FULFILLED; }; reject = () => { if (this.status ! == PENDING) return; this.status = REJECTED; }; }Copy the code
- Since every Promise object can call the then method, it should exist on the prototype object
const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'reiected'; class myPromise { constructor(executor) { executor(this.resolve, this.reject); } status = PENDING; resolve = () => { if (this.status ! == PENDING) return; this.status = FULFILLED; }; reject = () => { if (this.status ! == PENDING) return; this.status = REJECTED; }; This is very depressing. // Then (successCallback, failCallback) {if (this. Status === this) {successCallback(); } else if (this.status === REJECTED) { failCallback(); }}; }Copy the code
- The value of success should be passed when a successful callback is called, and the cause of failure should be passed when a failed callback is called
const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'reiected'; class myPromise { constructor(executor) { executor(this.resolve, this.reject); } status = PENDING; // By default, there is no success or failure, so the value should be undefined value = undefined; reason = undefined; Resolve = value => {if (this.status! == PENDING) return; this.status = FULFILLED; // This. Value = value; }; Reject = reason => {if (this.status! == PENDING) return; this.status = REJECTED; // This. Reason = reason; }; then(successCallback, failCallback) { if (this.status === FULFILLED) { successCallback(this.value); } else if (this.status === REJECTED) { failCallback(this.reason); }}; }Copy the code
- That’s where a radically simplified version of the Promise comes in.
What follows is the asynchrony part of the Promise