js异步编程

js语言的执行环境是"单线程":一次只能完成一件任务,如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。

这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。常见的浏览器无响应(假死),往往就是因为某一段Javascript代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。

为了解决这个问题,Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。

"同步模式"就是上一段的模式,后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的;"异步模式"则完全不同,每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。

一、回调函数

function f2(){
    console.log("f2") // f2的代码
}
function f1(callback){
    console.log("f1"); // f1的代码
    setTimeout(function(){
        callback();
    }, 1000);
}

> f1(f2)
f1
f2

同步变异步,f1不会阻塞f2。简单; 高度耦合,每个任务只能指定一个回调函数,无法return/try/catch/throw。

二、事件监听

function f2(){
    console.log("f2") // f2的代码
}
f1.on('done', f2); // 事件绑定 function f1(callback){ console.log("f1"); // f1的代码 setTimeout(function(){ f1.trigger('done'); }, 1000); } > f1(f2) f1 f2

事件驱动,可绑定多个,去耦合。

三、发布订阅

function f2(){
    console.log("f2") // f2的代码
}
jQuery.subscribe('done', f2); // 订阅信号 function f1(callback){ console.log("f1"); // f1的代码 setTimeout(function(){ jQuery.publish('done'); // 发布信号 }, 1000); } > f1(f2) f1 f2

类似事件监听,优于上者。

=== es6 ===

四、Promise

Promises对象是CommonJS工作组提出的一种规范

Promise是一个构造函数,方法有:all、reject、resolve、then、catch

resolve:成功

reject:失败

(复制到控制台查看运行结果)

function runAsync1(){
    var p = new Promise(function(resolve, reject){
        // 做一些异步操作
        setTimeout(function(){
            console.log('异步任务1执行完成');
            resolve('随便什么数据1');
        }, 1000);
    });
    return p;            
}
function runAsync2(){
    var p = new Promise(function(resolve, reject){
        // 做一些异步操作
        setTimeout(function(){
            console.log('异步任务2执行完成');
            resolve('随便什么数据2');
        }, 2000);
    });
    return p;            
}
function runAsync3(){
    var p = new Promise(function(resolve, reject){
        // 做一些异步操作
        setTimeout(function(){
            console.log('异步任务3执行完成');
            resolve('随便什么数据3');
        }, 2000);
    });
    return p;            
}

runAsync1()
.then(function(data){
    console.log(data);
    return runAsync2();
})
.then(function(data){
    console.log(data);
    return '直接返回数据';  // 这里直接返回数据
})
.then(function(data){
    console.log(data);
});

all:并行执行,谁跑得慢,以谁为准进行回掉

Promise
.all([runAsync1(), runAsync2(), runAsync3()]) // 并行
.then(function(results){
    console.log(results);
});

race:并行执行,谁跑得快,以谁为准进行回掉

Promise
.race([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
    console.log(results);
});
function getNumber(){
    var p = new Promise(function(resolve, reject){
        // 做一些异步操作
        setTimeout(function(){
            var num = Math.ceil(Math.random()*10); // 生成1-10的随机数
            if(num <= 5){
                resolve(num); // 成功,获取数字
            }
            else{
                reject('数字太大了'); //失败,传递参数
            }
        }, 2000);
    });
    return p;            
}

getNumber()
.then(
    function(data){ // 成功
        console.log('resolved');
        console.log(data);
    }, 
    function(reason, data){ // 失败
        console.log('rejected');
        console.log(reason);
    }
);
// 这个和上面功能一样,但是上面有异常不会卡死
getNumber()
.then(function(data){
    console.log('resolved');
    console.log(data);
})
.catch(function(reason){
    console.log('rejected');
    console.log(reason);
});

五、generator

=== es7 ===

六、async/await

async-awaitpromisegenerator的语法糖

参考资料

https://www.cnblogs.com/whybxy/p/7645578.html

https://www.cnblogs.com/chenshufang/p/9927536.html

https://segmentfault.com/a/1190000011526612?utm_source=tag-newest

http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html?bsh_bid=1736591883

未完待续。。。

原文地址:https://www.cnblogs.com/fogmisty/p/10382284.html