promise

MDN document

1. Introduce the promise

// Send a request to the server
// /student? Class =1 Get the information of class students
// /score? StuId =[1,2,3] returns student score information
// /jige? Score =90 determines a pass
    $.ajax({
            url: '/student'.method: 'get'.data: {
                    class: 1
            },
            success: function (result) {
                    // result=> student information
            $.ajax({
                url: '/score'.method: 'get'.data: {
                        stuId: result.map(item= > item.id)
                },
                success: function (result) {
                    // result=> Student score information
                    $.ajax({
                            / /...}); }}); }});Copy the code
  1. Callback hell: Continuing to do things in the last callback function, and continuing to call back (callback hell is a common occurrence in AJAX requests for real projects) => asynchronous requests, inconvenient code maintenance

  2. Promise was created to solve callback hell in asynchronous requests: it is a design pattern that ES6 provides a built-in JS class Promise to implement.

function ajax1() {
    return new Promise(resolve= > {
        $.ajax({
            url: '/student'.method: 'get'.data: {
                    class: 1
            },
            success: resolve
        });
    });
        }

function ajax2(arr) {
    return new Promise(resolve= > {
        $.ajax({
            url: '/score'.method: 'get'.data: {
                    stuId: arr
            },
            success: resolve
        });
    });
}

function ajax3() {
    return new Promise(resolve= > {
        $.ajax({
            url: '/jige'.// ...
            success: resolve
        });
    });
}
Copy the code
ajax1().then(result= > {
                return ajax2(result.map(item= > item.id));
        }).then(result= > {
                return ajax3();
        }).then(result= >{});Copy the code
  1. Use async instead
async function handle() {
    let result = await ajax1();
    result = await ajax2(result.map(item= > item.id));
    result = await ajax3();
    // The result is the information obtained after three asynchronous requests
}
handle();
Copy the code

2. The concept of promise

1. executor

Promises are used to manage asynchronous programming and are not asynchronous in themselves: The executor function will be executed immediately when a new PROMISE is made (except that we normally handle an asynchronous operation within the executor function).

new Promise([executor]) // [executor] execution functions must be passed
Copy the code
let p1 = new Promise(() = > {
            console.log(1); / / = > 1
        });
        console.log(2); / / = > 2
// Perform 1 immediately
		
Copy the code
let p1 = new Promise(() = > {
            setTimeout(_= > {
                    console.log(1);
            }, 1000);
            console.log(2);
        });
console.log(3);

// Execute the promise function and print 2, then 3, then 1
Copy the code
let p1 = new Promise(() = > {
            setTimeout(_= > {
                    console.log(1);
            }, 1000);
            console.log(2);
    });
console.log(3); 
/ / 2, 3, 1
Copy the code

2. The three states and values of the promise

  1. Three state

Pending Initial state

A big pity represents successful operation (resolved)

Rejected indicates that the operation fails

  1. The value value

PROMISE has a VALUE of its own that records the outcome of the success (or failure) =>[[PromiseValue]]

let p1 = new Promise((resolve, reject) = > {
        setTimeout(_= > {
                Resolve /reject: [[PromiseStatus]]/[[PromiseValue]]
                // Once the state is changed, there is no use executing resolve, reject
                resolve('ok');
                reject('no');
        }, 1000);
      }); 
Copy the code

3. Then method of promise

  1. new Promise“Is executed firstexecutorFunction, where an asynchronous operation of the task is started (variously: it is placed in the EventQuque task queue) and continues execution.
  2. p1.thenBased on the THEN method, two functions are stored (which have not yet been executed); whenexecutorThe asynchronous operation in the function ends, based onresolve/rejectControls the Promise state to determine implementationthenOne of the stored functions.
let p1 = new Promise((resolve, reject) = > {
    setTimeout(_= > {
        let ran = Math.random();
        console.log(ran);
        if (ran < 0.5) {
                reject('NO! ');
                return;
        }
        resolve('OK! ');
    }, 1000);
});
    // THEN: Sets the processing method after success or failure
    // Promise.prototype.then([resolvedFn],[rejectedFn])
p1.then(result= > {
        console.log('Success:' + result);
}, reason= > {
        console.log('Failure:' + reason);
}); 
Copy the code

Practice: 1.

let p1 = new Promise((resolve, reject) = > {
            console.log(1)
            resolve(100);
            console.log(2)}); p1.then(result= > {
    console.log('Success:' + result);
}, reason= > {
    console.log('Failure:' + reason);
});
console.log(3);
// 1 2 3 Success: 100
Copy the code
let p1 = new Promise((resolve, reject) = > {
    // resolve/reject execution, whether in an asynchronous operation or not,
    // all methods need to wait for then to complete
    // the corresponding method in then is executed after the state is changed.
    // => This is an asynchronous operation (so many people say PROMISE is asynchronous), and a microtask operation
            resolve(100);
    });
p1.then(result= > {
        console.log('Success:' + result);
}, reason= > {
        console.log('Failure:' + reason);
});
console.log(3);


    // 3 output 100
Copy the code
  1. Create a succeeded/failedPROMISEThe instance
    let p1 = new Promise((resolve, reject) = > {
                    resolve(100);
             }) 
// Create a successful PROMISE instance. This can also be used instead
    //=> Promise.resolve(100)
    // => Promise.reject(0)
	

Copy the code

4. THEN the chain

let p1 = new Promise((resolve, reject) = > {
            resolve(100);
    }) // Create a successful PROMISE instance;

let p2 = p1.then(result= > {
        console.log('Success:' + result);
        return result + 100; 
}, reason= > {
        console.log('Failure:' + reason);
        return reason - 100;
});

let p3 = p2.then(result= > {
        console.log('Success:' + result);
}, reason= > {
        console.log('Failure:' + reason);
}); 
    // Success 200 success 100

Copy the code
  1. THENMethod ends with a new onePromise instanceChain (THEN)
[[PromiseStatus]]:'pending'
[[PromiseValue]]:undefined
Copy the code
  1. p1thisnew PromiseThe instance that comes out, success or failure, depends onexecutorWhen the function executes, it executesresolveorrejectDetermined, orexecutorException errors in function execution also change the instance state to failed
  2. p2/p3This is done every timethenReturns the status of the new instance fromthenStored in theMethod execution resultsTo determine the final state (the result of the execution of a method in the previous THEN, which method will be executed in the next THEN)
  • Any execution that throws an exception, whether it is a successful method execution or a failed method execution (both methods in THEN), changes the state of the instance tofailure
  • Method if you return aNew PROMISE instance, returns the result of success or failure of the instance, and determines whether the current instance succeeds or fails
  • The rest is basically to make the instance successful (the method returns the value of the current instance: the result of the previous THEN method is passed to the method of the next THEN).
  1. practice
Promise.resolve(1)
     .then(result= > {
            console.log(` success:${result}`); 1 / / success
            return result * 10; 
    }, reason= > {
            console.log(` failure:${reason}`);
    }).then(result= > {
            console.log(` success:${result}`); 10 / / success
    }, reason= > {
            console.log(` failure:${reason}`);
    });
Copy the code
new Promise((resolve) = >{
           resolve(a) // => An error is reported and the status changes to Failed
    })
    .then(result= > {
            console.log(` success:${result}`); 
            return result * 10; 
    }, reason= > {
            console.log(` failure:${reason}`); //=> Fail A is not defined
    })
    // The state is successful. It just doesn't return a result
    .then(result= > {
            console.log(` success:${result}`); //= undefined successfully
    }, reason= > {
            console.log(` failure:${reason}`); 
    }); 
Copy the code
Promise.resolve(10)
      .then(result= > {
            console.log(` success:${result}`); 
            return Promise.reject(result * 10);
    }, reason= > {
            console.log(` failure:${reason}`);
    }).then(result= > {
            console.log(` success:${result}`);
    }, reason= > {
            console.log(` failure:${reason}`); 
    }); 
    // Success 10 failure 100
Copy the code
  1. You can also write one function or no function in TEHN

.then(fn)

.then(null,fn)

When a THEN is encountered, a successful or failed method is executed. If the method is not defined in the current THEN, the next corresponding function is continued

 Promise.reject(10).then(result= > {
			console.log(` success:${result}`);
			return result * 10;
		}).then(null.reason= > {
			console.log(` failure:${reason}`); 10 / / failure
		}); 
Copy the code

5. catch

Promise.prototype.catch(fn) ===> .then(null,fn)

Promise.resolve(10).then(result= > {
			console(a);//=> An error is reported and the status changes to failed
		}).catch(reason= > {
			console.log(` failure:${reason}`); // a is not defined
		}); 
Copy the code

6. Promise.all

MDN document

Promise.all([promise1, promise2]).then(success1, fail1)
Copy the code
  1. The result returned is onePROMISE instance(ALL instance), requiring each item in the ARR array to be a new PROMIE instance.
  2. PROMISE.ALLIs to wait for instance states in all arraysFor the successVALUE is a collection that stores the result returned by each instance in the ARR.
  3. If an instance in the ARR is in the failed state, the ALL Instance is also in the failed state.
let p1 = Promise.resolve(1);
let p2 = new Promise(resolve= > {
        setTimeout(_= > {
                resolve(2);
        }, 1000);
});
let p3 = Promise.reject(3);

Promise.all([p2, p1,p3]).then(result= > { // with p3 you fail, without p3 you succeed.
        // The returned results are grouped in the order in which instances are written in ARR, not first-come-first-executed
        / / (2, 1]
        console.log(` success:${result}`); // Success [2 1]
}).catch(reason= > {
        console.log(` failure:${reason}`);
}); 
Copy the code
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) = > {
  setTimeout(resolve, 100.'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) = > {
  console.log(values);
});
// expected output: Array [3, 42, "foo"]
Copy the code

7. Promise.race

MDN document

 Promise.race([promise1, promise2]).then(success1, fail1)
Copy the code
  • Promise1 and promise2Just one successSuccess1 is called;
  • Promise1 and promise2All it takes is one failureIt calls fail1;
  • In short, whoever succeeds or fails first is considered the success or failure of race.
  1. Different from ALL,RACE is a RACEThat is, whichever ARR completes first is the result of the “RACE instance”.
const promise1 = new Promise((resolve, reject) = > {
  setTimeout(resolve, 500.'one');
});

const promise2 = new Promise((resolve, reject) = > {
  setTimeout(resolve, 100.'two');
});

Promise.race([promise1, promise2]).then((value) = > {
  console.log(value);
  // Both resolve, but promise2 is faster
});
// expected output: "two"
Copy the code

8. ES7 provides a syntactic sugar for the PROMISE operation: async/await

  1. async
  • asyncIs to return the result of an ordinary function toSTATUS=RESOLVEDandVALUE=RETRNA PROMISE instance of the structure
  • asyncThe most important role is to cooperateawaitBecause once await is used in a function, the current function must be decorated with async
async function fn() {
        return 10;
}
console.log(fn());
Copy the code

  1. awaitWill wait for the presentpromiseIs returned only if the returned status isRESOLVEDThat is, the returned RESULT is assigned to RESULT.
  2. awaitNot synchronous programming, asynchronous programming (microtask) : When the code executes to this line (line first), build an asynchronous microtask (wait for the PROMISE to return the result and AWAIT the code below the AWAIT to be queued).

A piece of code:

let p1 = Promise.resolve(100);
async function fn() {
    console.log(1);
    let result = await p1;
    console.log(result);
}
fn();
console.log(2); 
	
Copy the code

Output: 1 2 100

let p1 = Promise.resolve(100);
let p2 = new Promise(resolve= > {
        setTimeout(_= > {
                resolve(200);
        }, 1000);
});
let p3 = Promise.reject(3);

async function fn() {
        console.log(1);
        // Have 2 await
        let result = await p2;
        console.log(result); / / 200
        let AA = await p1;
        console.log(AA); / / 100
}
fn();
console.log(2);
Copy the code

4. If a promise is in a failed state, then await will not return the result and the code under await will not continue to execute (await only if the promise is in a successful state).

let p3 = Promise.reject(3);
async function fn() {
        let reason = await p3;
        console.log(reason);
}
fn();
Copy the code

Question 9.

1.

async function async1() {
        console.log('async1 start');
        await async2();
        console.log('async1 end');
}
async function async2() {
        console.log('async2');
}
console.log('script start');
setTimeout(function () {
        console.log('setTimeout');
}, 0)
async1();
new Promise(function (resolve) {
        console.log('promise1');
        resolve();
}).then(function () {
        console.log('promise2');
});
console.log('script end'); 
Copy the code
  • The answer:
script start
async1 start
async2
promise1
script end
async1 end
promise2
undefined
setTimeout
Copy the code
  • Resolution:
  1. The main thread runs from top to bottom, creating async1, async2.
async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}
async function async2() {
    console.log('async2');
}
console.log('script start');
Copy the code

console.log(“script start”) => script start 2. When setTimout is encountered, set timer 1. Belongs to macro task, 0ms => execute task (set timer is synchronous task, and how many seconds to execute, belongs to asynchronous macro task)

setTimeout(function () {
    console.log('setTimeout');
}, 0)
Copy the code
  1. Execute async1(), console.log(” async1 start “) =>async1 start
  2. encounter
await async2();
Copy the code

Async2 () is executed immediately (the code after await), but the code below this line needs to wait until the correct promise result is returned, that is, the line or lines below this line belong to the asynchronous task (microtask), which we will name microtask 2. => async2

  1. Continue executing the code in the main thread, encountered
new Promise(function (resolve) {
    console.log('promise1');
    resolve();
}).then(function () {
    console.log('promise2');
});
Copy the code

The new Promise is a synchronous task that executes executor immediately. So promise1 is output. Resolve () is an asynchronous operation (microtask) that stores the response to an asynchronous queue using.then(). Name it microtask 3. => promise1

  1. Continue executing tasks in the main thread
console.log('script end'); 
Copy the code

Output script end => script end

  1. The synchronization tasks in the main thread are finished, and the asynchronous tasks in the event queue begin to be executed.First microtask, then macro task.
    • At this time, microtasks in the task queue have microtasks 2 and 3. Macro tasks have timer 1.
  2. Perform microtask 2: =>async1 end
  3. Perform microtask 3: =>promise 2
  4. Run a macro task (timer 1) : =>setTimeout

Question 2.

console.log(1);
setTimeout(_= > { console.log(2); }, 1000);
async function fn() {
        console.log(3);
        setTimeout(_= > {  console.log(4); }, 20);
        return Promise.reject();
}
async function run() {
        console.log(5);
        await fn();
        console.log(6);
}
run();
// perform about 150MS
for (let i = 0; i < 90000000; i++) {}
setTimeout(_= > {
        console.log(7);
        new Promise(resolve= > {
                console.log(8);
                resolve();
        }).then(_= > { console.log(9); });
}, 0);
console.log(10);
Copy the code

The answer:

1
5
3
10
4
7
8
9
2
Copy the code

Resolution:

  1. console.log(1) => 1
  2. Set up theThe timer 1, output after 1000ms =>2.
    setTimeout(_= > { console.log(2); }, 1000);
Copy the code
  1. Create the fn() function, only
async function fn() {
    console.log(3);
    setTimeout(_= > {  console.log(4); }, 20);
    return Promise.reject();
}
Copy the code
  1. Create the run() function
async function run() {
        console.log(5);
        await fn();
        console.log(6);
}
Copy the code
  1. Implement the run ()
async function run() {
        console.log(5);
        await fn();
        console.log(6);
}
Copy the code
  • Output 5 =>5
  • toawait fn()Executed immediatelyfn(), and the asynchronous code below it, need to wait for fn to return the success state will be executed.
  • Set the following code toMicro task 2(that is, the result of fn execution is output after success6).
  1. Perform fn ()
async function fn() {
    console.log(3);
    setTimeout(_= > {  console.log(4); }, 20);
    return Promise.reject();
}
Copy the code
  • Output 3 =>3
  • Set the timer. namedThe timer 3. 20 ms output4.
  • Return a failed state
  • Microtask 2 will not execute because it failed.
  1. In circulation
for (let i = 0; i < 90000000; i++) {}
Copy the code

About 150MS is required, that is, wait 150MS 8. Set timer 4

setTimeout(_= > {
        console.log(7);
        new Promise(resolve= > {
                console.log(8);
                resolve();
        }).then(_= > { console.log(9); });
}, 0);
Copy the code
  1. Output 10 = >10
  2. At this point, the main thread task is complete and the task queue starts to execute.Micro task first, macro task later. There are no microtasks to perform. So perform the macro task.
  3. Timer 3 has been timed and can be executed =>4
  4. If timer 4 is executed, output 7 =>7
  5. Timer 4new promise
  • Executor executes first and prints 8 =>8.
  • Resolve () is a microtask that is put into a queue. Named microtask 5 (executes the first method stored in the later THEN method)
  1. When a microtask appears in the queue, the microtask is executed regardless of whether the macro task has already been completed. Output microtask 5 =>9
  2. Performing macro task 1 =>2

10. Written promise