由于javascript本身是单线程模型,这里主要通过Callbacks,Listeners,Control Flow Libraries ,Promises四种方式来实现异步操作。
Reference:
           1.http://sporto.github.io/blog/2012/12/09/callbacks-listeners-promises/
           2.http://www.cnblogs.com/scy251147/archive/2013/03/26/2981814.html

一、Callbacks(函数回调)

让我们首先以函数回调方式来开头,这种方式也是最基本,同时也是大家都知道的异步实现方法。
现在我们有两个函数:Function1,Function2,调用顺序是先调用完Function1,然后调用Function2,如果Function1是一个耗时操作的话,那么Function2就被阻塞住了。
所以在这里我们尝试使用异步试试:

<script type="text/javascript">
function ajaxRequest(container,callback)
{
$.ajax({
url: "GetTitle",
type: "post",
success: function (data) {
container.append(data.message);
callback();
}
});
} function Function1(callback) {
setTimeout(function () {
ajaxRequest($(".container"),callback);
}, 1000);
} function Function2()
{
$(".container").append("Function2执行完毕");
} Function1(Function2);
</script>
<div class="container"></div>

最后我们得到的结果是:

程序先输出“Function1执行完毕”,然后再输出“Function2执行完毕”,符合预期。
这样做的好处就是方便,但是坏处就是如果执行的函数过多的话,需要一层套一层来进行,代码显得很乱,不容易维护。

顺便提一下,如果规定Funtion1执行完毕,才能执行Function2的话,那么我们就无需这么麻烦的设置回调了。直接利用下面代码:

Function1();

Function2();

即可。但是这样出现一个问题,就是最后输出结果是一块儿输出的。也就是会在同一时刻输出"Function1执行完毕Function2执行完毕"。

这是由于JS内部机制导致的,在JS内部,会将所有的更新UI操作排到最后进行,所以会导致同时输出。

要解决这个问题很简单,只需要利用:

Function1();

setTimeout(Function2,100);即可

二、Listeners(事件监听)

事件监听是Jquery里面非常著名,也是采用的非常多的处理方式。比如说下面代码:

$(".submit").on("click",function(){})

就是通过监听按钮的点击事件来执行后续的操作。

下面看代码模拟:

<script type="text/javascript">

    var eventable = {
on: function (event, cb) {
$(this).on(event, cb);
},
trigger: function (event) {
$(this).trigger(event);
}
} var TriggerDone = function (self) {
self.trigger('done');
} var Function3 = {
run: function () {
var self = this;
setTimeout(function () {
$.ajax({
url: "GetTitle",
type: "post",
success: function (data) {
$(".container1").append(data.message);
TriggerDone(self);
}
});
}, 500);
}
} var Function4 = {
run: function () {
var self = this;
setTimeout(function () {
$(".container1").append("Function4执行完毕");
TriggerDone(self);
},500);
}
} $.extend(Function3, eventable);
$.extend(Function4, eventable); Function3.on('done', function (event) {
Function4.run();
}); Function4.on('done', function () {
$(".container1").append("任务完成。");
}); Function3.run(); </script>
<div class="container1" style="color:brown"></div>

同样,我们得出了和第一种方式一样的结果,两个函数均为异步进行。

三、PUB/SUB(发布订阅模式,也就是观察者模式)

所谓的发布订阅模式就是指,源负责发布,然后一个或者多个目标进行接收订阅,一旦有新的信息,会主动推送给订阅者。

下面我们采用Ben Alman的Tiny Pub/Sub插件来完成,这是一个Jquery插件,你可以在这里下载:https://github.com/cowboy/jquery-tiny-pubsub

<script src="~/Content/ba-tiny-pubsub.min.js"></script>
<script type="text/javascript">
var Function5 = {
run: function () {
setTimeout(function () {
$.ajax({
url: "Home/GetResult",
type: "post",
success: function (data) {
$(".container2").append(data.message);
jQuery.publish("done");
}
});
}, 500);
}
} var Function6 = {
run: function () {
setTimeout(function () {
$(".container2").append("Function6执行完毕");
}, 500);
}
}
Function5.run(); jQuery.subscribe("done", Function6.run); </script>
<div class="container2"></div>

得到的最终结果是:AjaxFunction执行完毕.Function6执行完毕,这也完全符合我们的预期。

四、Promises对象

首先这个对象的介绍可以follow这个网站:http://wiki.commonjs.org/wiki/Promises/A  还有这个:http://www.html5rocks.com/zh/tutorials/es6/promises/

其目的是为异步编程提供统一接口。

每一个promise 对象都有一个then方法,可以指定回调函数。这样我们只需要以 func1().then(func2) 的形式进行调用即可。

<script type="text/javascript">
var Function7 = function () {
var deferred = $.Deferred();
alert(deferred.state());
setTimeout(function () {
$.ajax({
url: "Home/GetResult",
type: "post",
success: function (data) {
$(".container3").append(data.message);
if (deferred.state() === "pending") {
deferred.notify("正在处理中....");
}
deferred.resolve(); //可以带上参数进行传参操作。
}
});
}, 500);
return deferred.promise();
} var Function8 = function () {
var deferred = $.Deferred();
setTimeout(function () {
$(".container3").append("Function8执行完毕");
deferred.resolve();
}, 500);
return deferred.promise();
} $.when(Function7()).then(Function8).then(function () {
$(".container3").append("全部执行完毕");
});
</script>
<div class="container3"></div>

运行起来的时候,我们发现,事情是按照我们预想的方向发展。依次按顺序输出了: AjaxFunction执行完毕  Function8执行完毕  全部执行完毕。

这样写的功能非常强大,当我们有很多的函数需要规定执行顺序的时候,我们可以利用这种方式进行链式执行。同时由于promise提供的强大的错误处理手段,不用担心整体的崩溃。

粗略的写道这里,还希望你能够欣赏。有时间的话,准备专门详细研究下JQuery的Promise,敬请期待。

JavaScript及其异步实现的更多相关文章

  1. javascript的异步编程

    同步与异步 介绍异步之前,回顾一下,所谓同步编程,就是计算机一行一行按顺序依次执行代码,当前代码任务耗时执行会阻塞后续代码的执行. 同步编程,即是一种典型的请求-响应模型,当请求调用一个函数或方法后, ...

  2. JavaScript 的异步和单线程

    问题 Q:下面的代码是否能满足sleep效果? var t = true; setTimeout(function(){ t = false; }, 1000); while(t){ } alert( ...

  3. [译]理解Javascript的异步等待

    原文链接: https://ponyfoo.com/articles/understanding-javascript-async-await 作者: Nicolás Bevacqua 目前async ...

  4. javascript中异步和闭包产生的困惑

    这里我不打算大谈特谈什么是异步,什么是闭包,这些内容在博客园都已经写的够多的了,但是这些内容出现的多,并不代表所有初学者都已经撑握了,所以我还是打算,用一个比较常见的示例来分析一下,或许能让对这个问题 ...

  5. 理解Javascript的异步等待

    目前async / await特性并没有被添加到ES2016标准中,但不代表这些特性将来不会被加入到Javascript中.在我写这篇文章时,它已经到达第三版草案,并且正迅速的发展中.这些特性已经被I ...

  6. JavaScript及其异步实现续:Promise让一切更简单

    在写这篇文章之前,我参考了以下文章.所以我文中的例子都是精准的,而且有循可依.下面抛出例子的链接: Understanding JQuery.Deferred and Promise Deferred ...

  7. JavaScript编程异步助手:Promise

    异步模式在Web编程中变得越来越重要,对于Web主流语言JavaScript来说,这种模式实现起来不是很利索,为此,许多JavaScript库(比如 jQuery和Dojo.AngularJS)添加了 ...

  8. 漫话JavaScript与异步·第一话——异步:何处惹尘埃

    自JavaScript诞生之日起,频繁与异步打交道便是这门语言的使命,并为此衍生出了许多设计和理念.因此,深入理解异步的概念对于前端工程师来说极为重要. 什么是异步? 程序是分"块" ...

  9. JavaScript的异步机制

    我们经常说JS是单线程的,比如node.js研讨会上大家都说JS的特色之一是单线程的,这样使JS更简单明了,可是大家真的理解所谓JS的单线程机制吗?单线程时,基于事件的异步机制又该当如何 1 先看下两 ...

随机推荐

  1. iOS网络-05-AFNetwoking原理及常用操作

    AFN的六大模块 NSURLConnection,主要对NSURLConnection进行了进一步的封装,包含以下核心的类: AFURLConnectionOperation AFHTTPReques ...

  2. Cocos2d-x 基础元素

    看过本章,然后实践之后,应该会掌握以下的认识: 1.Cocos2d-x引擎的基本运转过程 2.Cocos2d-x引擎的一些初始设置 3.对导演及图层及现实对象的认识 4.如何定义自己的显示对象 *:f ...

  3. Mac显示隐藏文件的终端命令

    显示:defaults write com.apple.finder AppleShowAllFiles -bool true隐藏:defaults write com.apple.finder Ap ...

  4. 生命游戏/Game of Life的Java实现(转)

    首先简单介绍一下<生命游戏> 生命游戏其实是一个零玩家游戏.它包括一个二维矩形世界,这个世界中的每个方格居住着一个活着的或死了的细胞.一个细胞在下一个时刻生死取决于相邻八个方格中活着的或死 ...

  5. windows分离系统文件和用户数据

    2013/12/17更新:使用了一段时间,开机时有时会出现一些错误,不过不影响正常使用,不能忍的是会经常更新,所以暂时不推荐使用. 为了方便地重装系统,同时保留用户数据,想到了分离windows系统文 ...

  6. dubbo学习之服务消费者

    1.简介 上节讲了如何发布一个dubbo服务,这节主要讲如何进行消费,创建一个消费者. 2.详细步骤 2.1 项目目录结构 2.2 创建maven项目 这里演示时其实通过一个main方法就可以了,没必 ...

  7. SAM4E单片机之旅——19、CAN间通信

    CAN协议具有良好的可靠性,在工业中应用广泛.这次就先熟悉CAN的基本功能. 开发板有两个CAN,每个CAN有8个信箱.这次内容是从CAN0的信箱0发送数据到CAN1的信箱0. 除本次使用的功能外,C ...

  8. SQLPLUS连接oracle

    SQLPlus 在连接时通常有三种方式 1. sqlplus / as sysdba 操作系统认证,不需要数据库服务器启动listener,也不需要数据库服务器处于可用状态.比如我们想要启动数据库就可 ...

  9. jQuery Validate 表单验证插件----通过name属性来关联字段来验证,改变默认的提示信息,将校验规则写到 js 代码中

    一.下载依赖包 网盘下载:https://yunpan.cn/cryvgGGAQ3DSW  访问密码 f224 二. 添加一个另外一个插件jquery.validate.messages_cn.js. ...

  10. Spring学习笔记之 Spring IOC容器(二) 之注入参数值,自动组件扫描方式,控制Bean实例化方式,使用注解方式

     本节主要内容:    1. 给MessageBean注入参数值    2. 测试Spring自动组件扫描方式    3. 如何控制ExampleBean实例化方式    4. 使用注解方式重构Jdb ...