1. Understand the Promise
Promise is known as a solution to asynchronous programming in JS. Before you can simulate implementing promises, you first need to understand the features of promises.
1. A Promise (instance of promise) has three states: initial waiting-pending, successful Resolved and Failed. The state of a promise can be changed only once, from “Pending” to “Resolved” or “Rejected”. 2. A promise can change its state in three ways: from Pending to Resolved when resolve is called, and from Pending to Rejected when reject or an exception is thrown within the executive function. 3. If multiple callback functions are specified for the same PROMISE, all corresponding callback functions will be executed when the PROMISE changes to the corresponding state. 4. How to determine the result status of p.teng () return Promise? This is a big pity. If the callback function rejected () returns a promise value of string, undefined, and so on, the new promise will become a pity. Data is the returned value ③ if the callback returns a Promise object. Return value The result and state of the promise object is the result and state of the new promise. Throw err=>{throw err} so that when using a promise’s then chain call, err=>{throw err} You can specify the last failed callback (2) any previous exception is passed to the last failed callback (6). Interrupt the promise chain: When using the promise chain call, interrupt in the middle and do not call the following callback function method: Promise return new Promise(()={})
2. Simulation implementation of Promise
Implement the then, Catch, all, race, resolve, reject methods in Promise. ES6 syntax is used.
1.MyPromise overall structure
Class MyPromise {// Constructor function constructor(executor) {} // specifies the success and failure of the callback function, Return a new Promise then(resolvedCallBack, RejectedCallBack = error => {throw error}) {} return a new promise catch(rejectedCallBack) {} * @param {promise []} Promises * @return: promise () {promise () : promise (); */ static race(promises) {} /** * @author: forceddd * @desc: * @param ArrayOfPromises * @return: If all promises are successful, the promise data that returns a success state is an array of all promise success data. promise */ static all(promises) { } /** * @author: forceddd * @desc: * The state and result of the returned value of the passed promise are determined by the state and result of the parameter promise * @param {any} data * @return: Static resolve(data) {} /** * @author: forceddd * @desc: Error: return a promise with a failed state */ static reject(error) {}}Copy the code
2. Implementation of the constructor
Constructor (executor) {this.status = 'pending'; // Constructor (executor) {this.status = 'pending'; // State of the current instance this.data = undefined; // This. CallBacks = []; // Store until the promise completes, that is, while the state is still pending, [{resolveCb,rejectCb}] // The arrow function makes this point to this in the constructor. Otherwise, this in resolve and reject points to window. Const resolve = data => {// Status can only be changed once. Pending if (this.status! == 'pending') return; // Change the promise state to success this.status = 'resolved'; // Store success value this.data = data; If (this.callbacks.length) {setTimeout(() => {setTimeout() => { This.callbacks. ForEach (cbObj => cbobJ.resolvedCallback (data))})}} const reject = error => {//status can only be modified once Pending if (this.status! == 'pending') return; // Change the promise state to failed this.status = 'rejected'; // Store failure information this.data = error; If (this.callbacks.length) {setTimeout(() => {setTimeout() => { This.callbacks. ForEach (cbObj => cbobj. rejectedCallBack(error))})}} Executor (resolve, reject)} catch (error) {// If an exception is raised, the promise changes to Rejected reject(error)}}Copy the code
3. Then the implementation of the
// If no rejectedCallBack is passed, the default function will be executed and an exception will be thrown. Return then promise to failed then(resolvedCallBack, RejectedCallBack = error => {throw error}) {// Add a judgment condition resolvedCallBack = because I will pass a null to catch resolvedCallBack typeof resolvedCallBack === 'function' ? resolvedCallBack : _ => _; Return new MyPromise((resolve, reject) => {/** * @desc: then return * @1. If an exception is thrown while executing a callback, a promise error returns a failure. If the return value of the callback is not a Promise object, returning a successful Promise data is the return value of the callback * @ 3. * @param: cb * @return: */ const handleReturn = cb => {let res; Try {res = cb(this.data); Res instanceof MyPromise //3. If the return value of the callback function is a Promise, the state and result of the promise will be used as the state and result of the return promise. res.then( data => resolve(data), Error => reject(error)) resolvedCallBack(this.data) // Then (resolve, reject) //2 If the return value of the callback is not a PROMISE object, return a successful Promise data: resolve(res)} catch (error) {//1. Reject (error)}} if (this.status === 'pending') {// The pending state callback has been declared while the instance is still running CallBacks store the specified callback function in the callBacks // Then the return value of the callBacks is determined by the return value of the callBacks. // this.callbacks. Push ({resolvedCallBack, rejectedCallBack}) this.callbacks. Push ({resolvedCallBack: _ => handleReturn(resolvedCallBack), RejectedCallBack :_ => handleReturn(rejectedCallBack)}) /* Execute */} else if (this.status === = 'resolved') { setTimeout(() => handleReturn(resolvedCallBack)); } else { setTimeout(() => handleReturn(rejectedCallBack)); }})}Copy the code
4. The realization of the catch
Return this. Then (null, rejectedCallBack)}Copy the code
5. Implement Resolve and Reject
/** * @author: forceddd * @desc: * Passing in a promise returns the promise * @param {any} data * @return: Return a promise */ static resolve(data) {return data instanceof MyPromise? data : new MyPromise((resolve) => { resolve(data); }); } /** * @author: forceddd * @desc: Do not pass in a promise * @param {any} reason * @return: */ reject(error) {return new MyPromise((_, reject) => reject(error)); }Copy the code
6. The realization of the race
/** * @author: forceddd * @desc: promises * @param {promise []} Promises * @return: Static race(promises) {// Return a promise return new MyPromise((resolve, resolve, promise) Reject) => {promises. ForEach (promise => {// Promise = promise instanceof MyPromise? promise : MyPromise.resolve(promise); Then (resolve, reject)})})}Copy the code
7. The realization of all
/** * @author: forceddd * @desc: Promise * @param {promise []} Promises * @return: Promise () promise () {promise () : promise () {promise () : promise () {promise () : promise () {promise () : promise () {promise () : promise () {promise () : promise () {promise () : promise () {promise () : promise () {promise () : promise (); promise */ static all(promises) { let resolveCount = 0; Const results = new Array(promises. Length)// Create an Array of promises that are the same length as Promises. Return new MyPromise((resolve, reject) => {promise. ForEach ((promise, reject)) Index) => {// Convert elements that are not promises to promises. Promise = Promise instanceof MyPromise? promise : MyPromise.resolve(promise); promise.then( data => { results[index] = data; resolveCount++; resolveCount === promises.length && resolve(results); Reject (reject); reject (reject); reject (reject);Copy the code