This article is based on the previous two articles:

JS asynchronous programming: Promise uses method combing

JS asynchronous programming: event queues and event loops

Promise in depth

thenReturn result summary

Executing the THEN method returns some brand new Promise instance P2

How did p2’s state and value change?

  • Regardless of the execution is based onp1.thenThe storeonfulfilledCallback/onrejectedCallbackWhich of the two methods
  • An error is reported if the method executes
    • If a brand new one is returned from the methodPromiseInstance, then “brand new PromiseThe success and failure of “instance” determines the success and failure of P2
    • If it doesn’t returnpromise,[[PromiseState]]:fulfiled [[PromiseResult]]: The return value of either method
  • If method execution fails: p2[[PromiseState]]:rejected , [[PromiseResult]]: Error cause
let p1 = new Promise((resolve, reject) = > {
    resolve('OK');
    //reject('NO');
});
let p2 = p1.then(result= > {
    console.log('P1 success -- >', result);
    return Promise.reject(10);
}, reason= > {
    console.log('P1 failure -- >', reason);
});
let p3 = p2.then(result= > {
    console.log('P2 success -- >', result);
}, reason= > {
    console.log('P2 failure -- >', reason);
    return Promise.resolve(10);
});

p3.then(result= > {
    console.log('P3 success -- >', result);
}, reason= > {
    console.log('P3 failure -- >', reason);
    return Promise.resolve(10);
});
console.log(1);
Copy the code

Will resolve (” OK “); Note results:

The promise chain continues/penetrates the summary

If onfallledCallback/onrejectedCallback is not passed, the state and result are “deferred” to the next callback that should be executed in the same state.

new Promise((resolve, reject) = > {
        resolve('OK');
    }).then(null.null)
    .then(result= > {
        console.log('success -- >', result);
    }, reason= > {
        console.log('failure -- >', reason);
    })
Copy the code

Equivalent to (internal processing) :

new Promise((resolve, reject) = > {
        resolve('OK');
    }).then(result= >result ,reason= >Promise.reject(reason) )
    .then(result= > {
        console.log('success -- >', result);
    }, reason= > {
        console.log('failure -- >', reason);
    })
Copy the code
new Promise((resolve, reject) = > {
        resolve('OK');
       // reject('NO');
    }).then(null /*result=>result*/ , null /* reason=>Promise.reject(reason) */ )
    .then(result= > {
        console.log('success -- >', result);
    }, reason= > {
        console.log('failure -- >', reason);
    }).then(result= > {
        console.log('success -- >', result);
    }, reason= > {
        console.log('failure -- >', reason);
    }); 
Copy the code

Resolve to print:

Reject the print:

Catch is just a syntactic sugar for then, dealing with things that are done in a failed state

Promise.prototype.catch = function (onrejectedCallback) {
    return this.then(null, onrejectedCallback);
};
Copy the code
new Promise((resolve, reject) = > {
    resolve('OK');
    // reject('NO');
}).then(result= > {
    console.log('success -- >', result);
}).then(result= > {
    console.log('success -- >', result);
    return Promise.reject('xx');
}).catch(reason= > {
    console.log('failure -- >', reason);
});
Copy the code

Resolve to print:

Reject the print:

Skip all other processing and go straight to the final catch

new Promise((resolve, reject) = > {
    resolve('OK');
    // reject('NO');
}).then(result= > {
    console.log('success -- >', result);
}).then(result= > {
    console.log('success -- >', result);
    return Promise.reject('xx');
}).catch(reason= > {
    console.log('failure -- >', reason);
});
Copy the code

Don’t skip

Promise.all / Promise.race

The Promise. All method was used in the previous article. Here are a few examples to understand how to use it

Promise.all([Promise array]) The Promise array requires that each item in the array be as much as possible a Promise instance. Return A new Promise instance, A, which succeeds or fails depending on whether each promise instance in the array succeeds or fails. If one of the promise instances fails, A is A failure, and A is A success only if all of them succeed

Promise.race: The first Promise instance to know its state, whether it succeeds or fails, determines whether A succeeds or fails

 function fn(interval) {
    return new Promise((resolve, reject) = > {
        setTimeout(() = > {
            resolve(interval);
        }, interval);
    });
}
let p1 = fn(3000);
let p2 = fn(1000);
let p3 = Promise.resolve(0);

Promise.all([p1, p2, p3]).then(results= > {
    // Regardless of who knows the state first, the order of the final results should be the same as the order in which the array was passed
    console.log(results);
}); 
Copy the code

After the 3 s:

function fn(interval) {
    return new Promise((resolve, reject) = > {
        setTimeout(() = > {
            resolve(interval);
        }, interval);
    });
}
let p1 = fn(3000);
let p2 = fn(1000);
let p3 = Promise.reject(0);

Promise.all([p1, p2, p3]).then(results= > {
    // Regardless of who knows the state first, the order of the final results should be the same as the order in which the array was passed
    console.log(results);
}).catch(reason= > {
    // If a failure occurs, All fails immediately, and the result is the cause of the current instance failure
    console.log(reason);
});

Copy the code

Print 0 immediately

Demand processing:

const api1 = () = > {
    return new Promise(resolve= > {
        $.ajax({
            url: '/api1'.success(result1){ resolve(result1); }}); }); };const api2 = () = > {
    return new Promise(resolve= > {
        $.ajax({
            url: '/api2'.success(result2){ resolve(result2); }}); }); };const api3 = () = > {
    return new Promise(resolve= > {
        $.ajax({
            url: '/api3'.success(result3){ resolve(result3); }}); }); };Copy the code

Api1 / API2 / API3 serial request:

api1().then(result1= > {
    return api2();
}).then(result2= > {
    return api3();
}).then(result3= >{});Copy the code

Better serial requests:

(async function () {
    let result1 = await api1();
    let result2 = await api2();
    let result3 = awaitapi3(); }) ();Copy the code

Parallel request:

Promise.all([api1(), api2(), api3()]).then(results= >{});Copy the code

async / await

Async/await: ES7 raises syntactic sugar for generator + promise

– MDN async function

The aWAI T expression suspends the entire async function execution process and gives it control, resuming the process only after the promise-based asynchronous operation it is waiting for has been fulfilled or rejected. The resolve value of the promise is treated as the return value of the await expression. Use the async/await keyword to use normal try/catch blocks in asynchronous code

Points to note:

  1. Async: function modifier that controls a function to return a Promise instance

    async function fn() {
        return 10;
    }
    console.log(fn());
    Copy the code

  2. An internal execution error returns a failed promise instance with the reason for the failure

    async function fn() {
        console.log(a)
    }
    console.log(fn());
    Copy the code

  3. Return a promise on your own

    async function fn() {
        return Promise.resolve(1);
    }
    console.log(fn());
    
    Copy the code

  4. If an exception is caught inside the function, it is still successful

    async function fn() {
        try{
            console.log(a)
        }catch(e){}
        return 10
    }
    console.log(fn());
    Copy the code

The main purpose of using async is to use await inside a function

function fn() {
    await 1; //Uncaught SyntaxError: await is only valid in async function
} 
Copy the code
  1. awaitYou should place a promise instance behind it. The code we’re writing isn’t, and the browser will turn it into a promise instanceawait 1 -> await Promise.resolve(1)
  2. awaitIn the interrupt function body,awaitThe expression will pause the entireasynC function execution process and give it control. Only waiting forawaitIf a later Promise instance is successful, the code is stopped. If a later Promise instance fails, the code is stopped.
  3. awaitAre asynchronous microtasks. Encountered in the body of the functionawaitThe following code suspends execution and places them as a task in the microtask queue of the EventQueue
function api(interval) {
    return new Promise((resolve, reject) = > {
        setTimeout(() = > {
            resolve(interval);
        }, interval);
    });
}

async function func() {
    // await 1; //-> await Promise.resolve(1);

    let result1 = await api(1000);
    console.log(result1);

    let result2 = await api(3000);
    console.log(result2);
}
func();
Copy the code

Await string parallelism

There are two functions:

var resolveAfter2Seconds = function resolveAfter2Seconds() {
    console.log("starting slow promise");
    return new Promise(resolve= > {
        setTimeout(function () {
            resolve("slow");
            console.log("slow promise is done");
        }, 2000);
    });
};

var resolveAfter1Second = function resolveAfter1Second() {
    console.log("starting fast promise");
    return new Promise(resolve= > {
        setTimeout(function () {
            resolve("fast");
            console.log("fast promise is done");
        }, 1000);
    });
};
Copy the code

Different running methods have different results:

Successive (serial)

// sequential: sequential /[sɪ t ɪ t ə l]/
var sequential = async function sequential() {
    console.log('==SEQUENTIAL START==');
    const slow = await resolveAfter2Seconds();
    console.log(slow);
    const fast = await resolveAfter1Second();
    console.log(fast);
};
sequential()
Copy the code

serial

Simultaneous (parallel)

// concurrent: concurrent /[kənˈkʌrənt]/
var concurrent = async function concurrent() {
    console.log('==CONCURRENT START with await==');
    const slow = resolveAfter2Seconds();
    const fast = resolveAfter1Second();
    console.log(await slow);
    console.log(await fast);
};
concurrent()
Copy the code

The first two lines will run directly in sync and stop when we encounter await

Awai t interrupt function body, await expression suspends the whole asyn C function execution process and gives it control. The suspended code will not be executed until the promise instance behind the await is successful. If the promise instance behind the await fails, the code below will not be executed.

Await slow equals await resolveAfter2Seconds()

So the result is:

console.log(await slow);
console.log(await fast)
Copy the code

When do you wait for slow to end, and when do you print two

If so:

// concurrent: concurrent /[kənˈkʌrənt]/
var concurrent = async function concurrent() {
    console.log('==CONCURRENT START with await==');
    const slow = resolveAfter2Seconds();
    const fast = resolveAfter1Second();
    console.log(await fast);
    console.log(await slow);
};
concurrent()
Copy the code

Promise.all sync mode:

var concurrentPromise = function concurrentPromise() {
    console.log('==CONCURRENT START with Promise.all==');
    return Promise.all([resolveAfter2Seconds(), resolveAfter1Second()])
        .then((messages) = > {
            console.log(messages[0]);
            console.log(messages[1]);
        });
};
Copy the code

Parallel (also equivalent to parallel)

// parallel: parallel /[ˈpærəl]/
var parallel = async function parallel() {
    console.log('==PARALLEL with await Promise.all==');
    await Promise.all([
        (async() = > {let result = await resolveAfter2Seconds();
            console.log(result); }) (), (async() = > {let result = await resolveAfter1Second();
            console.log(result); }) ()); };Copy the code

Two word execution functions have their own internal private context and do not affect each other. In the context of both self-executing functions, both functions are run synchronously. So this is equivalent to:

var parallel2 = async function parallel() {
    console.log('==PARALLEL with await Promise.all==');
    var slow =  (async() = > {let result = await resolveAfter2Seconds();
        console.log(result); }) ()var fast =  (async() = > {let result = await resolveAfter1Second();
        console.log(result); }) ()await Promise.all([slow,fast]);
};
Copy the code

var parallelPromise = function parallelPromise() {
    console.log('==PARALLEL with Promise.then==');
    resolveAfter2Seconds().then((message) = > console.log(message));
    resolveAfter1Second().then((message) = > console.log(message));
};
Copy the code

Output the same: