JavaScript异步编程

JavaScript异步编程

    javascript的语言的执行环境是“单线程”。即一次只能完成一件任务。

    一般情况下,在浏览器端,耗时很长的操作都应该异步执行,避免浏览器失去响应。所谓异步执行,不同于同步执行(程序的执行顺序与任务的排列顺序是一致的、同步的),每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。

    javascript的异步处理能够很好的应对大型Web程序的复杂性,交付快速相应的代码。

    javascript的异步处理技巧有:回调函数、事件监听、发布订阅、Promise等

1.回调函数

    回调函数是异步编程最基本的方法。

   回调函数的优点:简单、容易理解。

   假设有两个函数fun1() fun()2,且fun2()等待fun1()执行结果

   这里将fun2写成fun1的回调函数

function fun1(callback){
    setTimeout(function(){
        //fun1的代码
        callback();
    },1000);
}

//执行代码
fun1 ( fun2 )


   缺点:当遇到高阶函数(多层嵌套),代码的可读性差
   
step1(function(res1){
    step2(function(res2){
        step3(function(res3){
            //...
        });
    });
});

    回调函数还有一个问题:我们在回调函数之外无法捕获到回调函数的异常。

     为什么异步代码回调函数中的异常无法被最外层的try/catch语句捕获?

           异步调用一般分为两个阶段,提交请求和处理结果,这两个阶段之间有事件循环的调用,它们属于两个不同的事件循环,彼此没有关联。

           异步调用一般以传入callback的方式来指定异步操作完成后要执行的动作。而异步调用本体和callback属于不同的事件循环。

          try/catch语句只能捕获当次事件循环的异常,对callback无能为力。

          也就是说,一旦我们在异步调用函数中扔出一个异步I/O请求,异步调用函数立即返回,此时,这个异步调用函数和这个异步I/O请求没有任何关系。

2.事件监听

     采用事件驱动模式。任务的执行不取决于代码的顺序,而取决于某个事件是否发生。
     
     当fun1发生done事件,就执行fun2:
function fun1(){
    setTimesout(function(){
    //fun1的任务代码
    fun1.trigger('done');
    },1000)
 
}

fun1.trigger('done') 表示执行完后,立即触发done事件,从而开始执行fun2

fun1.on('done',fun2);

3.发布订阅

 假设存在一个“信号中心”,某个任务执行完成,就向信号中心“发布”(publish)一个信号,其他任务可以向信号中心“订阅”(subscribe)这个信号,从而知道什么时候可以开始执行。这就是发布订阅 模式。

function fun1(){
    setTimeout(function (){
        // fun1的任务代码
        $.publish('done');
    },1000);
}

//fun2向信息中心订阅 'done' 信号

$.subscribe('done',fun2);
这里采用了第三方jQuery的一个插件订阅。

4.Promise

Promises对象是CommonJS工作组提出的一种规范,目的是为异步编程提供统一的接口。Promises被逐渐用作一种管理异步操作回调的方法,但出于它们的设计,它们远比那个有用得多。Promise允许我们以同步的方式写代码,同时给予我们代码的异步执行。

Promise对象:就是把每个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。

fun1()写法如下:
function fun1(){
    var dfd = $.Deferred();
    setTimeout(function (){
        //fun1的代码
        dfd.resolve();
    },1000);
    return dfd.promise
}


如下,fun1的回调函数fun2

fun1().then(fun2);


若是有多个回调函数可以

fun1().then(fun2).then(fun3);

//指定发生错误的回调函数

fun1().then(fun2).fail(fun3)

该方式的优点在于,回调函数变成了链式写法,程序的流程可以看得很清楚。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值