前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript异步编程

JavaScript异步编程

作者头像
奋飛
发布2019-08-15 10:11:47
4320
发布2019-08-15 10:11:47
举报
文章被收录于专栏:Super 前端Super 前端Super 前端

Javascript语言的执行环境是”单线程”(single thread)。所谓”单线程”,就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。 Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。 “异步模式”非常重要。在浏览器端,耗时很长的操作都应该异步执行,避免浏览器失去响应,最好的例子就是Ajax操作。在服务器端,”异步模式”甚至是唯一的模式,因为执行环境是单线程的,如果允许同步执行所有http请求,服务器性能会急剧下降,很快就会失去响应。 然而,异步执行最大的问题就是执行顺序。 假定有两个函数f1和f2,后者等待前者的执行结果。

function f2() {
    console.log("f2");
}

一、回调函数

function f1(callback) {
    console.log("f1");
    setTimeout(function(){
        callback();
    }, 1000);
}
// 执行
f1(f2);

优点是简单、容易理解和部署; 缺点是不利于代码的阅读和维护,各个部分之间高度耦合(Coupling),流程会很混乱,而且每个任务只能指定一个回调函数。

二、事件监听

这里采用的jQuery的写法

var eventable = {
    on: function(event, cb) {
        $(this).on(event, cb);
    },
    trigger: function (event, args) {
        $(this).trigger(event, args);
    }
}

var f1 =  {
    run: function() {
        setTimeout(function(){
            // f1执行逻辑
            console.log("f1");
            f1.trigger("done");
        }, 1000);
    }
};

$.extend(f1, eventable);
f1.on("done", f2);
f1.run();

优点是比较容易理解,可以绑定多个事件,每个事件可以指定多个回调函数,而且可以”去耦合”(Decoupling),有利于实现模块化; 缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰。

补充:<注意上述f1的写法> 当使用eval()函数或者是Function构造函数以及使用setTimeout()传一个字符串参数时都会发生“双重解释”。

eval("console.log('Hello Eval!')");
var sayHello = new Function("console.log('Hello Function!')");
setTimeout("console.log('Hello setTimeout!')", 1000);

这些操作不能在初始化的解析过程中完成的,也就是说在JavaScript代码运行的同时必须新启动一个解析器来解析新的代码。性能消耗较大。

console.log('Hello Eval!')
var sayHello = function() {
    console.log('Hello Function!')
};
setTimeout(function(){
    console.log('Hello Function!')
}, 1000)

三、发布/订阅

使用jQuery插件https://github.com/cowboy/jquery-tiny-pubsub

jQuery.subscribe("done", f2);

function f1(){
    // f1执行逻辑
    console.log("f1");
    setTimeout(function(){
        jQuery.publish("done");
    }, 1000);
}

f1();
jQuery.unsubscribe("done", f2);     // 取消订阅

这种方法的性质与”事件监听”类似,但是明显优于后者。因为我们可以通过查看”消息中心”,了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行。

四、Promises对象

function f1(){
    var dfd = $.Deferred();
  setTimeout(function () {
    // f1的任务代码
        console.log("f1");
    dfd.resolve();
  }, 500);
    // 在原来的deferred对象上返回另一个deferred对象,后者只开放与改变执行状态无关的方法(比如done()方法和fail()方法),屏蔽与改变执行状态有关的方法(比如resolve()方法和reject()方法),从而使得执行状态不能被改变。
  return dfd.promise();
}

f1().then(f2);

好处:如果一个任务已经完成,再添加回调函数,该回调函数会立即执行。所以,你不用担心是否错过了某个事件或信号。这种方法的缺点就是编写和理解,都相对比较难。

参考地址:http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015年11月25日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、回调函数
  • 二、事件监听
  • 三、发布/订阅
  • 四、Promises对象
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档