Nothing, I just hope you pick me! — The time traveler’s wife

preface

To recall the fear of being ruled by callback hell when I first started JavaScript, 😂😂😂!

The solution lies in it – Promise and Async/await

Recommended vscode plug-in Code Runner, can run Code snippets. Learn the sharp weapon. It’s just running on a Node environment

Promise

A Promise has the following states: Once the state changes, it cannot be changed.

Pending: The initial state, which is neither successful nor failed. Wait state transition

This is a pity: which means that the operation will be completed successfully. Then processing logic

Rejected: Indicates that the operation fails. You can handle logic in catch

Each THEN returns a new Promise instance

Api

// Create a fulfilled Promise instance.
Promise.resolve();
// Create a Promise instance with the Rejected state.
Promise.reject();
// then resolve {Function}
// The second parameter parameter rejected handles the Rejected state.
// If then handles the Rejected state, the return Promise instance is
// this is a pity, otherwise it will return the instance of Rejected.
Promise.prototype.then(resolve,rejected);
// Intercept the Fulfilled state implementation and return a fulfilled Promise instance
Promise.prototype.catch();
// Whatever state will be executed at the end
Promise.prototype.finally();
Returns Array [promiseRet,promiseRet]
Promise.all([promise,promise]);
// Returns the result of the fastest promise
Promise.race([promise,promise]);
Copy the code

appetizers

  • demo1
const demo1 = function _demo1(num) {
    return new Promise((resolve, reject) = > {
        if (num % 2= = =0) {
            // Pending state is very large
            resolve(num);
            return;
        }
        // Pending status to Rejected
        reject(num);
    });
};
demo1(2)
    .then(
        // Process the depressing state
        resolveData => {
            console.log('resolve-', resolveData);
        },
        // Handle the Rejected state, after which the catch will not be triggered.
        rejectData => {
            console.log('reject', rejectData);
        }
    )
    .then(data= > console.log('Still callable, data undefined', data));
    
    // this is a big pity. // this is a big pity.
    // resolve- 2
    // It can still be called with data undefined
Copy the code
  • demo2
const demo1 = function _demo1(num) {
    return new Promise((resolve, reject) = > {
        if (num % 2= = =0) {
            resolve(num);
            return;
        }
        reject(num);
    });
};
demo1(1)
    .then(
        resolveData= > {
            console.log('resolve-', resolveData);
        },
        rejectData => {
            console.log('reject', rejectData);
        }
    )
    .then(data= > console.log('Data undefined-', data))
    .catch(error= > console.log('catch:', error));
// If (1 = even) then (rejected) then (rejected
// reject 1
// Data undefined- undefined is still available
Copy the code
  • demo3
const demo1 = function _demo1(num) {
    return new Promise((resolve, reject) = > {
        if (num % 2= = =0) {
            resolve(num);
            return;
        }
        reject(num);
    });
};
demo1(3)
    .then(resolveData= > {
        console.log('resolve-', resolveData);
    })
    .then(data= > console.log('Data undefined-', data))
    .catch(error= > {
        console.log('catch-', error);
        return 'I dealt with Rejected';
    })
    // Verify that catch intercepts Rejected and returns a pity instance
    .then(data= > console.log('Catch' then-', data));
    // 3 is odd, the state changes to Rejected, and then rejects is passed to catch.
    // catch- 3
    // Catch the then- I deal with rejected
Copy the code

This process only deals with the fulfilled state and the catch intercepts the Rejected state

promise.then(resolve= >{}).then(resolve= >{}).then(resolve= >{}).catch(error= >{});
Copy the code

Promise to encapsulate the JQuery – Ajax

class AjaxUtil {
    static get(url, otherSetting = {}) {
        return new Promise((resolve, reject) = > {
            const ajaxGetSetting = {
                url: url,
                type: 'GET'.dataType: 'json'.success: data= > {
                    resolve(data);
                },
                error: error= >{ reject(error); }}; $.ajax(Object.assign(otherSetting, ajaxGetSetting)); }); }}// No need to pass callback.
AjaxUtil.get('/api/videos').then(data= > {
    document.getElementById('div').innerHTML = JSON.stringify(data);
});
Copy the code

Promise.all()

/** * const promise=Promise.all([promise,promise...] ); * @description: Promise. All returns a Promise instance with a reject * state and a reject */ state
Copy the code
  • Demo
const sleep = function _sleep(ms) {
    return new Promise(resolve= > {
        setTimeout((a)= > {
            resolve();
        }, ms);
    });
};
console.log('start');
const sleep1 = sleep(1000).then((a)= > {
    console.log('Take a break');
    return 'Tell him I'm sorry. I'm going to find a girl.';
});
const sleep2 = sleep(2000).then((a)= > {
    console.log('Take a two-second break');
    return 'Forget what should be forgotten, and face what can be in the future. ';
});
const sleep3 = sleep(3000).then((a)= > {
    console.log('Take a three-second break');
    return 'Boy, life isn't about books and assumptions. It's about feeling. ';
});
const sleep4 = sleep(4000).then((a)= > {
    console.log('Take a four-second break');
    return 'Everyone has bad days, but it can also remind you of the good things you didn't care about before. ';
});
const ret2 = Promise.all([sleep1, sleep2, sleep3, sleep4]);
ret2.then(data= > {
    // data is an array of all promise resolve results
    console.log(data);
});
console.log('end');
Copy the code
Rest one second rest two seconds rest three seconds rest four seconds [' Tell him I'm sorry, I'm going to find a girl ', 'Forget what I should forget and face what the future can be ',' child, life is not made by books and assumptions, it is made by the heart. ', 'Everyone has bad days, but it can also remind you of good things you didn't care about before.']Copy the code

Promise.all can be handy when you want to get the execution results of multiple asynchronous events and then do subsequent logic processing. But promise.all does not block subsequent code execution. It is comfortable to write code with synchronous coding thinking in conjunction with async/await.

Demo2

Verify the Promise. The Promise in the all parameter has a state of Rejected

const sleep = function _sleep(ms) {
    return new Promise(resolve= > {
        setTimeout((a)= > {
            resolve();
        }, ms);
    });
};
const sleep1 = sleep(1000).then((a)= > {
    console.log('Take a break');
    return 'Tell him I'm sorry. I'm going to find a girl.';
});
const sleep2 = sleep(2000).then((a)= > {
    console.log('Take a two-second break');
    return 'Forget what should be forgotten, and face what can be in the future. ';
});
const sleep3 = sleep(3000).then((a)= > {
    console.log('Take a three-second break');
    return 'Boy, life isn't about books and assumptions. It's about feeling. ';
});
const sleep4 = sleep(4000).then((a)= > {
    console.log('Take a four-second break');
    return 'Everyone has bad days, but it can also remind you of the good things you didn't care about before. ';
});
const sleep5 = sleep(5000).then((a)= > {
    console.log('Take a five second break');
    throw new Error('Simulated test failure situation');
});
const ret2 = Promise.all([sleep1, sleep2, sleep3, sleep4, sleep5]);
ret2.then(data= > {
    console.log(data);
    / / execute catch
}).catch(error= > {
    console.log(error.message);
});
Copy the code
Rest one second rest two seconds rest three seconds rest four seconds rest five seconds Simulate test failureCopy the code

Promise.race([promise,promise])

The first state to change, return that promise

const sleep = function _sleep(ms) {
    return new Promise(resolve= > {
        setTimeout((a)= > {
            resolve();
        }, ms);
    });
};
const sleep2 = sleep(2000).then((a)= > {
    console.log('Take a two-second break');
    return 'You can understand everything, but the only way to get to the bottom of it is to try. ';
});
const sleep3 = sleep(3000).then((a)= > {
    console.log('Take a three-second break');
    return 'Man is a lonely individual after all, even if you have been in the arms of others, the only difference between people, perhaps, is where you hide your loneliness. ';
});
const sleep4 = sleep(4000).then((a)= > {
    console.log('Take a four-second break');
    return 'Shunned and distrusted because I was abandoned by the one who should have loved me. ';
});
const ret = Promise.race([sleep2, sleep3, sleep4]);
ret.then(data= > {
    console.log(data);
});
Copy the code
You can learn about everything in two seconds, but the only way to get to the bottom of it is to try. Take a three-second break. Take a four-second breakCopy the code

Async/await

Use async/await all the time.

The async function returns an instance of Promise. The code is added to the microtask queue when await is encountered, and then returned from the function to continue executing the subsequent code.

Async /await is used on functions. And await cannot appear alone, it needs to be with async.

const async = async function _async() {
    // The execution encounters await, adds the task to the microtask queue, and returns. Continue to execute the following code
    const awaitRet = await Promise.resolve(1).then(data= > {
        console.log('resolve-then');
        return data;
    });
    console.log(awaitRet);
    console.log('Code behind await');
};
console.log('start');
async(a);console.log('end');
Copy the code
Start end resolve-then 1 awaitCopy the code
    const awaitRet = await Promise.resolve(1).then(data= > {
        console.log('resolve-then');
        return data;
    });
    console.log(awaitRet);
    console.log('Code behind await');
    // The following code can be easily interpreted as

Promise.resolve()
    .then((a)= > {
        const awaitRet = await Promise.resolve(1).then(data= > {
        console.log('resolve-then');
        return data;
        });
    })
    // code after await is added to the microtask queue
    .then((a)= > {
        console.log(awaitRet);
        console.log('Code behind await');
    });
Copy the code

Demo1

const awaitFunc = function _awaitFunc() {
    return Promise.resolve('awaitFunc').then(data= > {
        console.log(data);
        return 'awaitFunc-then-return-data';
    });
};
const async = async function _async() {
    // Wait for the await to finish before putting further code into the microtask queue
    await awaitFunc().then(data= > {
        console.log(data);
    });
    console.log('awaitFunc finishes printing ');
};
async(a);Copy the code
AwaitFunc awaitFunc-then-return-data awaitFunc is printed after executionCopy the code

Demo2

The subsequent code to await blocking is put into the microtask queue? Is it really so? Let’s do a demo to verify my idea.

const awaitFunc = function _awaitFunc() {
    return Promise.resolve('awaitFunc').then(data= > {
        console.log(data);
        return 'awaitFunc-then-return-data';
    });
};
const async = async function _async() {
    // Wait for the await to finish before putting further code into the microtask queue
    setTimeout((a)= > {
        console.log('Verify joining microtask queue --1');
    }, 0);
    await awaitFunc().then(data= > {
        console.log(data);
        setTimeout((a)= > {
            console.log('Verify joining microtask queue --2');
        }, 0);
    });
    console.log('awaitFunc finishes printing ');
};
async(a);Copy the code
AwaitFunc awaitFunc-then-return-data awaitFunc joins the microtask queue after the print validation is complete --1 validation joins the microtask queue --2Copy the code

If console.log(‘awaitFunc finishes printing ‘) is placed in the macro task queue, this code will not be executed before setTimeout. Hence the subsequent code blocked by await is put into the microtask queue of the current event loop. All microtasks will also be completed in this event loop.

Promise&async/await usage scenario

Writing asynchronous code with synchronous thinking is actually more in line with our thinking habits.

const sleep = function _sleep(ms, data) {
    return new Promise(resolve= > {
        setTimeout((a)= > {
            console.log(` rested${ms}Second `);
            resolve(data);
        }, ms);
    });
};
console.log('start');

const data = [
    'Tell him I'm sorry. I'm going to find a girl.'.'Forget what should be forgotten, and face what can be in the future. '.'Boy, life isn't about books and assumptions. It's about feeling. '.'Everyone has bad days, but it can also remind you of the good things you didn't care about before. '
];
const asyncFunc = function _async(data) {
    console.log('asyncFunc-start');
    const promises = [];
    for (let index = 0; index < data.length; index++) {
        promises.push(sleep(index, data[index]));
    }
    const ret = Promise.all(promises);
    console.log('Processing finished at the beginning');
    console.log('asyncFunc-end');
    return ret;
};
const retPromise = asyncFunc(data);
retPromise.then(data= > {
    console.log(data);
});
console.log('end');

Copy the code
Start asyncFunc-start asyncFunc-end end rest 0 seconds rest 1 seconds rest 2 seconds rest 3 seconds [' tell him sorry, I'm going to find a girl ', 'forget what should be forgotten, face the future everything can appear. 'Life isn't made by books and things, kid. Life is made by the heart.' and 'Everyone has bad days, but they remind you of the good things you never thought about before.']Copy the code

I want the above code to be executed sequentially in asyncFunc, processing promise. all first and then continuing to await the code.

  • Rewrite with async/await.
const sleep = function _sleep(ms, data) {
    return new Promise(resolve= > {
        setTimeout((a)= > {
            console.log(` rested${ms}Second `);
            resolve(data);
        }, ms);
    });
};
console.log('start');

const data = [
    'Tell him I'm sorry. I'm going to find a girl.'.'Forget what should be forgotten, and face what can be in the future. '.'Boy, life isn't about books and assumptions. It's about feeling. '.'Everyone has bad days, but it can also remind you of the good things you didn't care about before. '
];
const asyncFunc = async function _async(data) {
    console.log('asyncFunc-start');
    const promises = [];
    for (let index = 0; index < data.length; index++) {
        promises.push(sleep(index, data[index]));
    }
    const ret = await Promise.all(promises);
    console.log('Processing finished at the beginning');
    console.log('asyncFunc-end');
    return ret;
};
const retPromise = asyncFunc(data);
retPromise.then(data= > {
    console.log(data);
});
console.log('end');

Copy the code
Start asyncFunc-start end Rest 0 SEC rest 1 SEC rest 2 SEC rest 3 SEC finish processing at start asyncFunc-end [' Tell him sorry, I'm going to find a girl ', 'Forget what should be forgotten, face the future everything that can appear. 'Life isn't made by books and things, kid. Life is made by the heart.' and 'Everyone has bad days, but they remind you of the good things you never thought about before.']Copy the code

You can see that the code behind await is waiting for the promise.all microtask to complete before starting. Note the end printing timing. Async /await is also based on an event loop and does not block code execution. Otherwise the end should have been printed last.

Use async/await in loops

Forof,forin,fori loops can sense await

const data = [1.2.3];
const async = async function _async(data) {
    for (const index in data) {
        const item = data[index];
        const ret = await Promise.resolve(item)
            .then(data= > {
                console.log('First then');
                return data;
            })
            .then(data= > {
                console.log('Second then');
                return data;
            });
        console.log('await return value ', ret);
        console.log('Code after await'); }};async(data);

Copy the code
// fori
const data = [1.2.3];
const async = async function _async(data) {
    for (let index = 0; index < data.length; index++) {
        const item = data[index];
        await Promise.resolve(item)
            .then(data= > {
                console.log('First then');
                return data;
            })
            .then(data= > {
                console.log('Second then');
                return data;
            });
        console.log('Code after await'); }};async(data);

Copy the code
// forof
const data = [1.2.3];
const async = async function _async(data) {
    for (const item of data) {
        await Promise.resolve(item)
            .then(data= > {
                console.log('First then');
                return data;
            })
            .then(data= > {
                console.log('Second then');
                return data;
            });
        console.log('Code after await'); }};async(data);
Copy the code
The code after the first and the second then await the first and the second then await the code after the first and the second then await the codeCopy the code

Forin,forof,fori can all sense await

ForEach cannot sense await

const data = [1.2.3];
const async = async function _async(data) {
    data.forEach(async item => {
        const ret = await Promise.resolve(item)
            .then(data= > {
                console.log('First then');
                return data;
            })
            .then(data= > {
                console.log('Second then');
                return data;
            });
        console.log('await return value ', ret);
        console.log('Code after await');
    });
};
async(data);
Copy the code
The first then the first then the first then the second then the second then the second then the second then the second then await returns the value 1 await the code after await returns the value 2 await the code after await returns the value 3 await Next codeCopy the code