Callback vs Async.js vs Promise vs Async/await

Source: Internet
Author: User
Tags terminates throw exception

Demand:

A, read a| in turn b| C three files and terminates immediately if there is a failure.
B, simultaneous reading a| b| C three files and terminates immediately if there is a failure.

First, callback

需求A

  Let read = function (code) {if (code) {return true;    } else {return false;    }}let Readfilea = function (callback) {if (read (1)) {return callback (NULL, "111");    } else {return callback ("a Fail");    }}let Readfileb = function (callback) {if (read (1)) {return callback (NULL, "222");    } else {return callback ("B fail");    }}let Readfilec = function (callback) {if (read (1)) {return callback (NULL, "333");    } else {return callback ("C Fail");        }}readfilea (err, data) {if (err) {console.log ("Open file" + err);    Return } console.log ("Read A.txt succeeded!    Content: "+ data";            Readfileb (err, data) {if (err) {console.log ("Open file" + err);        Return } console.log ("Read B.txt succeeded!        Content: "+ data";                Readfilec (err, data) {if (err) {console.log ("Open file" + err);           Return } console.log ("Read C.txt succeeded!        Content: "+ data";    }); });});

Return

读取 a.txt 成功!内容:111读取 b.txt 成功!内容:222读取 c.txt 成功!内容:333

需求B: Too disgusting, not written, in short, very cumbersome.

Second, async.js

async.jsA detailed description of the library can be found in: [to be written]

需求A

async.series

var async = require("async");let read = function (code) {    if (code) {        return true;    } else {        return false;    }}let readFileA = function (callback) {    if (read(1)) {        return callback(null, "111");    } else {        return callback("a fail");    }}let readFileB = function (callback) {    if (read(0)) {        return callback(null, "222");    } else {        return callback("b fail");    }}let readFileC = function (callback) {    if (read(1)) {        return callback(null, "333");    } else {        return callback("c fail");    }}async.series([readFileA, readFileB, readFileC],    function (err, datas) {        if (err) {            console.log("open file " + err);        }        console.log(datas);        return;    });

When a second Readfileb () read fails:

Return

open file b fail[ '111', undefined ]

需求B

async.parallel

var async = require("async");let read = function (code) {    if (code) {        return true;    } else {        return false;    }}let readFileA = function (callback) {    if (read(1)) {        return callback(null, "111");    } else {        return callback("a fail");    }}let readFileB = function (callback) {    setTimeout(() => {        if (read(0)) {            return callback(null, "222");        } else {            return callback("b fail");        }    }, 1000);}let readFileC = function (callback) {    if (read(1)) {        return callback(null, "333");    } else {        return callback("c fail");    }}async.parallel([readFileA, readFileB, readFileC],    function (err, datas) {        if (err) {            console.log("open file " + err);        }        console.log(datas);        return;    });

When the second Readfileb () read fails (note that I added setTimeout to it, in order to reflect the difference from the serial result above):

Return

open file b fail[ '111', undefined, '333' ]

Summary: Benefits of Async.js and callback:

1, the code is less, solve the callback Hell pyramid defect

2, async in the second parameter callback function, you can handle the error uniformly (it is recommended to use different error classes to distinguish)

3, the result of successful return datas can be summarized into an array for easy processing

Third, Promise

Expand

Promise Knowledge

new Promise()
//  promise 在 new 的时候已经开始运行 new Promise(() => console.log("I have already started!"));

Return

I have already started!
promise.then(successCallback, failureCallback);
new Promise((resolve, reject) => resolve()).then(function (data) {    console.log("success");}, function (data) {    console.log("fail");})

Return

success
promise.catch(failureCallback)
// promise.catch(failureCallback) 是 promise.then(null, failureCallback) 的缩略形式new Promise((resolve, reject) => reject()).catch( function (data) {    console.log("fail");})

Return

fail
链式调用
// 链式调用的原理:then 函数会返回一个新的 promisenew Promise((resolve, reject) => reject()).then(function (data) {    console.log("success_1");}, function (err) {    console.log("fail_1");}).then(function (data) {    console.log("success_2");}, function (err) {    console.log("fail_2");});

Return

fail_1success_2
Questions

Q 1: then 函数 A new promise will be returned, but then both Successcallback and Failurecallback cannot invoke resolve () and reject (), and the new promise how to specify the most What about the final state?

Then
in Successcallback and Failurecallback. equivalent to
Do not return Resolve (undefined)
Return 1 Resolve (1)
Return Promise.resolve () Resolve ()
Return Promise.reject () Reject ()
Throw Error () Reject ()
return new Promise () And so on

Instead of the normal promise object, if the call Resolve/reject is not displayed, nothing happens, for example:

new Promise((resolve, reject) => {return 1;}).then(function (data) {    console.log("success");}, function (err) {    console.log("fail");});

Return

Without any output

Q 2:then function if successCallback and failureCallback both are null, what happens?

Nothing will happen, .then(null, null) as long as one of the parties is null equals to the next then to take over the callback

new Promise((resolve, reject) => reject())    .then(null, null)    .then(null, null)    .then(null, null)    .then(null, null)    .then(function (data) {        console.log("success_2");    }, function (err) {        console.log("fail_2");    });

So according to the above 2 questions revealed by the law , we can write the following elegant code :

// 链式调用的原理:then 函数会返回一个新的 promisenew Promise((resolve, reject) => resolve()).then((data) => {    console.log("success_1");}).then((data) => {    console.log("success_2");    throw Error("error");}).then((data) => {    console.log("success_3");}).catch((err) => {    

Return

success_1success_2Error: error ……

Note: .catch() you can also continue to connect .then() or.catch()

This achieves the following clear expression of the synchronization code of the other people's home:

try {    let result = syncDoSomething();    let newResult = syncDoSomethingElse(result);    let finalResult = syncDoThirdThing(newResult);    console.log(`Got the final result: ${finalResult}`);  } catch(error) {    console.log(error);}

So, 需求A :

Let read = function (code) {if (code) {return true;    } else {return false; }}let Readfilea = function () {return new Promise (function (resolve, reject) {if (read (1)) {Resolv        E ("111");        } else {reject ("a fail"); }    });} Let Readfileb = function () {return new Promise (function (resolve, reject) {if (read (1)) {Resolve (        "222");        } else {reject ("B fail"); }    });} Let Readfilec = function () {return new Promise (function (resolve, reject) {if (read (1)) {Resolve (        "333");        } else {reject ("C fail"); }    });} [Serial] Scenario: preload multiple resources sequentially, or enter. catch () Readfilea () if there is a failure in the middle. Then (data) {Console.log ("read A.txt succeeded!    Content: "+ data"; return Readfileb ();}). Then (the function (data) {Console.log ("read B.txt succeeded!    Content: "+ data"; return Readfilec ();}). Then (the function (data) {Console.log ("read C.txt succeeded!    Content: "+ data"; Return "read End";}). Then (funCtion (data) {Console.log (data); return;}). catch (function (err) {console.log ("Open file" + err);})

promiseVs事件监听

A. 事件监听 more of what happens on the same object more than once (e.g. KeyUp, touchstart, etc.)

And promise more of the performance of the object eventually to what state, and can not be changed.

But there is a magic type that is consistent, 事件监听 and the promise callback function that can bind multiple times to the response of the same event , as shown in the following example:

let promise = new Promise((resolve, reject) => {    console.log("I have already started!");    resolve();})setTimeout(() => {     promise.then(function (data) {        console.log("success_1");        throw new Error();    }, function (err) {        console.log("fail_1");    }); }, 2000);setTimeout(() => {     promise.then(function (data) {        console.log("success_2");    }, function (err) {        console.log("fail_2");    }); }, 4000);

Return

I have already started!//又等待了2秒success_1(node:13150) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error(node:13150) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.//又等待了2秒success_2

B. Unlike 事件监听 if the promise has succeeded or failed, and a callback function has been added over time, the callback can still be invoked successfully. The above example can also be reflected.

C. 事件监听 more attention to the precise timing of certain functions promise is more about responding to results.

Promise Extension API

Promise.resolve()And Promise.reject()

A quick way to manually create a promise that is already resolve or reject.

promise.all: You can implement 需求B:
//promise.all [并行] 场景:预加载多个资源,都完成后才能进入页面Promise.all([readFileA(), readFileB(), readFileC()]).then(function (datas) {    console.log(datas); //所有promise都resolve,返回array    return;}).catch(function (err) {    console.log("open file " + err); //只要有一个promise是reject,返回这个reject的value})
promise.race
//promise.race [并行] 场景:taskA:fetch图片,taskB:settimeout抛错,让两个task赛跑实现请求超时报错功能Promise.race([taskA(), taskB()]).then(function (data) { //进到resolve还是reject回调只取决于第一个确定状态的Promise    console.log(data);    return;}).catch(function (err) {    console.log("读取图片超时");})

Summary: Benefits of Promise and callback:

1, the code is less, solve the callback Hell pyramid defect

2. Catch can handle errors uniformly (it is recommended to distinguish between different error classes)

Iv. async/await 需求A:
Let read = function (code) {if (code) {return true;    } else {return false; }}let Readfilea = function () {return new Promise (function (resolve, reject) {if (read (1)) {Resolv        E ("111");        } else {reject ("a fail"); }    });} Let Readfileb = function () {return new Promise (function (resolve, reject) {if (read (1)) {Resolve (        "222");        } else {reject ("B fail"); }    });} Let Readfilec = function () {return new Promise (function (resolve, reject) {if (read (1)) {Resolve (        "333");        } else {reject ("C fail"); }    });}        Async function Test () {try {Let re_a = await Readfilea ();        Let Re_b = await readfileb ();        Let Re_c = await Readfilec (); Console.log ({re_a, Re_b, re_c}); If all succeeds, return: {re_a: ' 111 ', Re_b: ' 222 ', Re_c: ' 333 '}} catch (Err) {Console.log (err);//if B fails, return:b f  Ail}}test ();

Summary: Benefits of Async/await and callback:

1, the least amount of code, solve the problem of callback Hell Pyramid (Promise through then chain to solve the callback multi-layered callback pyramid, and now use async/await to further optimize it) (Promise-based async/await also tried to eliminate Promise

2. Catch can handle errors uniformly (it is recommended to distinguish between different error classes)

Expand

1, the Async function is the Generator function of the syntax of sugar, is not essentially synchronous code

2. Async is used to declare that a function is asynchronous, while an await (async wait) is used to wait for an asynchronous method to execute.

3,await can only appear in the Async function, so at the top of the code, we cannot use await, so add it. Then/catch to handle the final result or drop error is normal practice.

try {        let re_a = await readFileA();        let re_b = await readFileB();        let re_c = await readFileC();        console.log({re_a, re_b, re_c});    } catch (err) {        console.log(err);    }

Return

Error

Or the top level using an immediate execution function expression (iife)

(async () => {    try {        let re_a = await readFileA();        let re_b = await readFileB();        let re_c = await readFileC();        console.log({re_a, re_b, re_c});    } catch (err) {        console.log(err);    } })()

Return

{ re_a: '111', re_b: '222', re_c: '333' }

The above example can also be written like this:

async function test() {    try {        let re_a = await readFileA();        let re_b = await readFileB();        let re_c = await readFileC();        console.log({re_a, re_b, re_c}); //如果都成功,return: { re_a: '111', re_b: '222', re_c: '333' }    } catch (err) {        console.log(err); // 如果b失败,return: b fail    }}test().then(function(data){    console.log("success");},function(err){    

Return

{ re_a: '111', re_b: '222', re_c: '333' }success

4, see the above example, in fact, the Async declaration function returns a Promise object , which is the reason that await must be used in the async function. Async function calls do not cause blocking, and all of its internal blocking is encapsulated in an Promise object that executes asynchronously.

The difference is that theAsync declaration function can be achieved by the return value/throw exception to achieve the common Promise resolve ()/reject ()

The following is a peer relationship:

// async 函数async function foo () {  return 'a'}// Promisefunction foo () {  return Promise.resolve('a')}
// async 函数async function foo () {  throw new Error('error')}// Promisefunction foo () {  return Promise.reject(new Error('error'))}
Use promise.allRealize 需求B

Async/await also applies Promise.all , because the Promise.all itself returns the Promise object.

Let read = function (code) {if (code) {return true;    } else {return false; }}let Readfilea = function () {return new Promise (function (resolve, reject) {if (read (1)) {Resolv        E ("111");        } else {reject ("a fail"); }    });} Let Readfileb = function () {return new Promise (function (resolve, reject) {if (read (1)) {Resolve (        "222");        } else {reject ("B fail"); }    });} Let Readfilec = function () {return new Promise (function (resolve, reject) {if (read (1)) {Resolve (        "333");        } else {reject ("C fail"); }    });}        Async function Test () {try {Let re_a = await Readfilea ();        Let Re_b = await readfileb ();        Let Re_c = await Readfilec ();    Console.log ({re_a, Re_b, re_c});    } catch (Err) {Console.log (err); }}async function Test () {try {Let results = await promise.all ([ReadfiLeA (), Readfileb (), Readfilec (),]);    Console.log (results);    } catch (Err) {Console.log (err); }}test ();

# # # Reference

[Using promises]
Developer.mozilla.org/zh-cn/docs/web/javascript/guide/using_promises

[Understanding JavaScript's async/await]
1190000007535316

[Javascript.info-async/await]

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.