Home >Web Front-end >JS Tutorial >Detailed explanation of JavaScript asynchronous programming technology

Detailed explanation of JavaScript asynchronous programming technology

黄舟
黄舟Original
2017-02-27 14:23:411391browse

Detailed explanation of JavaScript asynchronous programming technology

Based on the browser's event polling mechanism (and the event polling mechanism in Node.js), JavaScript often Runs in an asynchronous environment. Due to the characteristics of the JavaScript language itself (which does not require programmers to control threads/processes), it is very important to solve asynchronous programming in js. It can be said that in a complete project, it is impossible for js developers not to face asynchronous operations. This article will introduce in detail several classic JavaScript asynchronous programming serialization methods, and will also briefly introduce the Promise sequential execution method provided by ES6.

1. Callback function

(1) Classic callback function method: nested inline function

Suppose we have an ajax() method, He receives a url parameter, initiates an asynchronous request to the address, and executes the second parameter - a callback function at the end of the request:

ajax(url,function(result){
    console.log(result);
});

It can be said that this method is used by almost every front-end developer. The callback function method, with such a callback mechanism, developers do not need to write code like the following to guess when the server request will return:

var result=ajax(url);
setTimeout(function(result){
    console.log(result);
},400);

You should be able to understand what I want to express here. We set a timer with a delay of 400 milliseconds, assuming that the ajax request we make will be completed within 400 milliseconds. Otherwise, we will operate on a result of undefined.
But there is a problem that gradually emerges as the project expands: if the scene requires us to have multiple layers of nested callback functions, the code will become difficult to read and maintain:

ajax(url0,function(result0){
    ajax(result0.url1,function(result1){
        ajax(result1.url2,function(result2){
            console.log(result2);
        });
    });
});

(2) Calling external functions

In order to solve the code confusion problem exposed by inline callback functions, we introduce external function calls to solve similar problems:

function handle2(result){
    console.log(result);
}function handle1(result){
    ajax(result.url,function(result){
        handle2(result);
    });
}
ajax(url,function(result){
    handle1(result);
});

By splitting inline functions in this way, we can call the optimization of external functions Method can greatly keep the code concise.

2. Develop a callback manager

Observing popular JavaScript process control tools, such as Nimble, Step, and Seq, we will learn a simple design pattern: control through a callback manager Asynchronous JavaScript execution process, the following is a key code example of a typical callback manager:

var Flow={};//设置next方法,在上一个方法完成时调用下一个方法Flow.next=function(){
    if(this.stack[0]){        //弹出方法栈中的第一个方法,并执行他
        this.stack.shift()();
    }
};//设置series方法,接收一个函数数组,并按序执行Flow.series=function(arr){
    this.stack=arr;    this.next();
};//通过Flow.series我们能够控制传入的函数的执行顺序Flow.series([        function(){
            //do something
            console.log(1);
            Flow.next();
        },        function(next){
            //do something
            console.log(2);
            Flow.next();
        }
]);

We initialized a Flow controller and designed a series for him and next two function attributes. Within the business method we wrote, the next method is triggered sequentially by calling Flow.next() at the end of the method; the asynchronous function is sequentially executed by executing the series method. This way of managing asynchronous function calls through the core controller simplifies our programming process, allowing developers to devote more energy to business logic.

3. Global mark control

(1) Simple counter control

Perhaps the asynchronous method introduced above still cannot meet the business scenarios in actual development: Suppose we have## There are three methods: #a(), b(), c(). A and b have no dependency and can be performed asynchronously. But c can only be triggered after both a and b are completed. In order to meet such a logical implementation, we add a global counter to control the execution flow of the code:

var flag=2;var aValue,bValue;function a(){
    aValue=1;
    flag--;
    c();
}function b(){
    setTimeout(function(){
        bValue=2;
        flag--;
        c();
    },200);
}function c(){
    if(flag==0){
        console.log("after a and b:"+(aValue+bValue));
    }
}
a();
b();

We set a global variable flag to monitor the completion of method a and method b. Method b simulates the network environment by setting a 200 millisecond timer, and will eventually call method c successfully after method b is executed. In this way, we realize the dependent calls to methods

a(), b(), c().

(2) Data-oriented control

When the above solution is applied in complex scenarios, the following problems will occur: the product has gone through multiple version iterations, and the c method relies on more methods, so The counter flag needs to be constantly changed; developers are changed during the product iteration process. When the above two situations occur, the logic of the code will become confusing. Whether the flag tag can remain concise and correct is largely affected by product iterations. Therefore, we propose data-oriented optimization improvements.

In real development scenarios, the reason for the existence of method dependencies is basically because of the existence of data dependencies. For the simple example above: method c depends on the results of the operations of method a and method b, rather than whether the flag is 0. Therefore, we can replace checking whether the marker has been set to 0 by checking whether the dependent method has completed data processing. In this example, we check whether aValue and bValue have completed assignment in the c method:

function c(){
    if(aValue!==undefined && bValue!==undefined){
        console.log("after a and b:"+(aValue+bValue));
    }
}

For a more general scenario, we modify the above code to the following:

var checkDependency={};var aValue,bValue;function a(){
    aValue=1;
    checkDependency.a=true;
    c();
}function b(){
    setTimeout(function(){
        bValue=2;
        checkDependency.b=true;
        c();
    },200);
}function c(){
    if(checkDependency.a && checkDependency.b){
        console.log("after a and b:"+(aValue+bValue));
    }
}
a();
b();

Through the data-oriented inspection method, when expanding in the future, we only need to add the checkDependency# to the new method

checkDependencyModify the object and check the existence of the corresponding attributes in the c method to achieve the sequential execution of asynchronous dependent methods.

4. ES6 new method—Promise class

In order to solve the complexity of asynchronous methods in JavaScript, the official introduced a unified control method:

var bool=false;/*
 * 新建一个Promise实例,向构造函数传入一个异步执行函数
 * 异步函数会接受两个参数,由Promise传入,对应then方法中传入的方法
 */var promise=new Promise(function(resolve,reject){
    setTimeout(function(){
        if(bool){            //根据执行情况相应调用resolve和reject
            resolve(bool);
        }else{
            reject(bool);
        }
    },200);
});//通过then向Promise实例传入解决方法promise.then(function resolve(result){
    console.log("success");
},function reject(result){
    console.log("failure");
});

The above example The code shows a basic Promise application. Perhaps the following chain call is more common in actual scenarios:

new Promise(function(res,rej){
    if(/*异步调用成功*/){
        res(data);
    }else{
        rej(error);
    }
}).then(function resolve(result){
    console.log("success");
},function reject(result){
    console.log("failure");
});

如果对Promise感兴趣的话,可以在网上寻找资料继续深入学习!
关于Promise的兼容性,通常web前端JavaScript代码中不会直接使用Promise(通过caniuse.com网站查询发现Android4.4不支持Promise)。如果特别想使用的,往往会在项目中附带一些补足兼容性的promise类库;而后端Node.js可以放心使用Promise类来管理异步逻辑。
Detailed explanation of JavaScript asynchronous programming technology

 以上就是详解JavaScript异步编程技术的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn