Javascript Asynchronous Investigation

Introduction

  • Sync task: line up on the main thread of task execution, only the first task is finished, you can perform a task after;
  • Asynchronous task: do not enter the main thread, into the task queue task, the task queue only notify the main thread, an asynchronous tasks can be carried out, this task will enter the main thread.

method:

  1. Callback callback
  2. Promise promise
  3. async/await

1. Callback

Node.js oldest directly reflects the concept of asynchronous programming is the callback. Its form is registered as a callback function A B, B to put in writing the last parameter A to register. After completing the registration task A, B will be called. For example, while we can read the file, execute other commands while, after reading the file is complete, we will file contents as an argument callback function returns. So that when no execution code or blocked waiting for the file I / O operations. This greatly improves the performance and can handle a large number of concurrent requests.

The disadvantage is that this syntax, each task can only specify a callback function . So in the past, if there is demand for multiple asynchronous operations, you need to wait between consecutive asynchronous operation on a number of operations performed and then the end of the next operation, the following code will appear :( also called callback hell)

getData(a => {
  getMoreData(a, b => {
    getMoreData(b, c => {
      getMoreData(c, d => {
        getMoreData(d, e => {
          console.log(e);
        })
      })
    })
  })
})

doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('Got the final result: ' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);

2.Promise / then

To solve this problem, ECMAscript 6 provides Promise concept.

Promise is an object, which represents an asynchronous operation (on behalf of future events will happen), as well as its execution state . Let's take a look at the constructor's Promise:

new Promise( function(resolve, reject) {...} /* executor */  );

PromiseArgument constructor is a function that we call him executor. with executor resolveand rejecttwo parameters, these parameters are also each function category is a Promise, each with a parameter value. Prototype is as follows:

Promise.resolve(value)
Promise.reject(value)

First mention, Promisethere are three 初始(pending)``、完成(fulfilled)states: 失败(rejected), .

When a new Promise, the code is: do some asynchronous operation, and then finally calls resolveand rejectone of the two. When the successful completion of the asynchronous task and returns, should be called resolveupon, and asynchronous tasks that failed with failure cause (usually an error object), calls rejectthe function.

  • Promise resolve method can change the state of the object is successful , the information may be transferred for subsequent processing in the function
  • Promise method may reject the state of the object is changed to a failure , the information may be transferred for subsequent processing in the function
  • If the asynchronous operation throws an error, calls the catch method specified callback function, handle the error, and then the method specified callback function, if the operation throws an error, catch will be captured

The idea here is: This allows asynchronous method can be like synchronization method that returns a thing , but not immediately return the final results of the implementation , but the return to a representative of future results can appear Promise objects . Then, according to the Promise object state , invoke a different callback function .

Here's what it calls the callback method: Promise.prototype.then(). Promise for the role instance is to add callback function changes state , the first parameter of this method is the callback function resolved state, the second parameter (optional) is the callback rejected state. then you can chain calls , because then the object is a Promise method itself will return. Use chained calls then, just hell callback code that becomes very clear looks like a chain of calls is as follows:

getData()
  .then(a => getMoreData(a))
  .then(b => getMoreData(b))
  .then(c => getMoreData(c))
  .then(d => getMoreData(d))
  .then(e => console.log(e));

doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
  console.log(`Got the final result: ${finalResult}`);
})
.catch(failureCallback);

However, in most cases, we do not need their own new Promise, but the use of Promise instance object has been created.

Promise advantages and disadvantages as follows: With Promise object, the process may be asynchronous operation to synchronous operation expressed, to avoid deeply nested callback function. The disadvantage is: immediately call the executor function when Promise constructor executes, mean, we can not cancel Promise, it will be executed immediately once the new, no-wait, can not be canceled midway. And if you do not set a callback function, internal Promise error will not be reflected to the outside.

Now we summarize, Promise represents an asynchronous operation, there will be a guarantee of future results, whether the result is good or bad, are distinguished by the state. Compared to a benefit of a registered callback function that can be detached from objects asynchronously and a callback function, by thena method to bind a callback function on the asynchronous operation (instead of registering a callback function on the function), which avoids the callback hell. Since then the method returns a Promise object, so we have very convenient method by calling the chain of nested callbacks to solve problems, and because there is a method Promise.all, it allows simultaneous execution of multiple operations simple.

3.async/await

async is ES7-only keywords associated with the asynchronous operation, and the Promise of great relevance. async is "asynchronous" shorthand, await can be considered async wait shorthand. async in the full name of the document is called the async functionmean async keyword must be written before the function declaration, to declare a function is asynchronous .

Syntactic sugar sentence, async function is a function of Promise. , The role of async is: make this function returns the object must be a Promise .

async function testAsync() {
    return "hello async";
}

const result = testAsync();
console.log(result); // Promise { 'hello async' }

Async function declarations, returns a Promise object. If the function return is not an object but a direct amount Promise, async will direct this amount by Promise.resolve () Promise encapsulated object. Promise because it is the object, naturally, we can use the old way: then () chain Promise to deal with this subject.

testAsync().then(v => {
    console.log(v);    // 输出 hello async
});

Described below with the corresponding await. await an operator, syntax is:

[return_value] = await expression;
  • Wherein expression can be a Promise object or to wait any value .
  • (If you wait Promise not to return the value itself).
  • If you are waiting for async function / Promise objects, conceptually speaking, is to wait for the completion of an asynchronous operation. So it will suspend execution of the current async function, waiting for Promise processing is complete . If normal processing Promise (Fulfilled), which resolve as the value of the callback function parameters await expression, then resume execution of the async funcion. (Although there have been blocked, but in fact the code is executed asynchronously, the function call async / await expression does not cause obstruction, because it is encapsulated inside all executed asynchronously in a Promise object. It must also await the async the reason function)
  • If the Promise to handle exceptions (rejected), await Abnormal expression of Promise will be thrown.
  • await operator can only be used in an asynchronous function async function, otherwise a syntax error.

Now, for example, time-consuming simulation with setTimeout asynchronous operation, take a look at not async / await how would you write

function takeLongTime() {
    return new Promise(resolve => {
        setTimeout(() => resolve("long_time_value"), 1000);
    });
}

takeLongTime().then(v => {
    console.log("got", v);
});

And If you are using async / await, will be this:

function takeLongTime() {
    return new Promise(resolve => {
        setTimeout(() => resolve("long_time_value"), 1000);
    });
} // 这个函数本身return的就是Promise 所以加不加 async 关键字都一样

async function test() {
    const v = await takeLongTime();
    console.log(v);
}

test();

These two codes are two ways to deal with (that is, the actual processing of the Promise object) asynchronous call difference is not obvious, even using async / await need to write some code, then it's Where is the advantage? Answer: Advantages async / await processing then that chain . Promise a single chain does not discover the advantages async / await, but if you need time to deal with then chain composed of a plurality of Promise, benefits can be manifested (very interesting, multilayered callback Promise to solve the problem by then chain and now with the async / await further optimize it).

Assuming a service, is completed in several steps, each step are asynchronous, but also on the result of the last step. We still use setTimeout to simulate asynchronous operation:

/**
 * 传入参数 n,表示这个函数执行的时间(毫秒)
 * 执行的结果是 n + 200,这个值将用于下一步骤
 */
function takeLongTime(n) {
    return new Promise(resolve => {
        setTimeout(() => resolve(n + 200), n);
    });
}

function step1(n) {
    console.log(`step1 with ${n}`);
    return takeLongTime(n);
}

function step2(n) {
    console.log(`step2 with ${n}`);
    return takeLongTime(n);
}

function step3(n) {
    console.log(`step3 with ${n}`);
    return takeLongTime(n);
}

// 现在用 Promise 方式来实现这三个步骤的处理

function doIt() {
    console.time("doIt");
    const time1 = 300;
    step1(time1)
        .then(time2 => step2(time2))
        .then(time3 => step3(time3))
        .then(result => {
            console.log(`result is ${result}`);
            console.timeEnd("doIt");
        });
}

doIt();

// c:\var\test>node --harmony_async_await .
// step1 with 300
// step2 with 500
// step3 with 700
// result is 900
// doIt: 1507.251ms

If async / await to achieve it, it would be like this:

async function doIt() {
    console.time("doIt");
    const time1 = 300;
    const time2 = await step1(time1);
    const time3 = await step2(time2);
    const result = await step3(time3);
    console.log(`result is ${result}`);
    console.timeEnd("doIt");
}

doIt();

Promise and the results achieved is the same as before, but this code is not much seems clear, almost as synchronization code

Summary: async function in the await expression, role is to make the async function suspended pending the outcome of Promise came out, then resumes parsing async function and return value. purpose async / await is simplified when using a plurality of synchronization behavior Promise .

Finally

Essentially, Promise is a certain function object is outgoing, we attach the callback function (callback) to use it, unlike the "old-fashioned" incoming callback, the callback function rather than passing those internal functions. The then multiple calls (), can be added to many callbacks, which will be performed in a separate insert by one order.

Promise of features - no wait, so perform async function without await the circumstances, it would be executed immediately return a Promise object, and will not be blocked behind the statement.

await Generally, all that is waiting for an async await completion function. But by Syntax, await wait can be any expression, the results of this expression is Promise objects or other values. Because async function returns a Promise object, it can be used to await the return value (Promise Lane resolve) to wait for a async function - this can also be said to await the completion of waiting for async function. But to be clear, and so it is actually a return value. Promise not to notice objects await etc., it can wait for the results of any expression, therefore, await behind the actual function call can be accessed by ordinary direct or amount.

If you wait until it is a Promise objects, await you busy, and it will block (which is used in the async function must await the reason .async function call does not cause obstruction, blocking all within it are encapsulated in a Promise asynchronous execution object) code behind, waiting Promise resolve the object, and then resolve the value obtained as the calculation result of the expression await.

Async has been described above will be followed by a function (function expression or the Lambda) as a return value Promise packaged object, and waits for the Promise await complete, and returns the result out of their resolve. It will make the code looks very much clear, almost as synchronization code

reference

The official document:

Rookie Tutorial:

Guess you like

Origin www.cnblogs.com/ZCplayground/p/11424719.html