前言

javascript的中的异步是很重要的概念,特别是ajax的提出,给整个web带来了很大的影响,今天就介绍下javascript的异步编程。

同步与异步

何为同步?何为异步呢?

同步:说白了就是程序一步一步从下向下执行,没有什么别的代码的跳动,就是按序执行,和在景区里女生上厕所是排队是一样的(每次女厕都是有好多人在排队)。可以看成是一个单线程问题。

异步:异步就是程序可以跳着执行,开始执行一段程序之后不用等返回结果就执行其他的代码,等结果返回之后在对结果进行处理,也就是可以在有限的时间内办好几件事情,提高效率,异步一般情况是多个线程问题。举个例子,还是上厕所的例子,A说需要5分钟搞定,B就可以5分钟之后过来,B可以在这5分钟干点别的事情。

所以说异步可以提高程序的执行效率,所以异步编程具有一定的好处,但是编写异步程序却不是那么容易的。

上面是我的理解,下面是摘自别人的文章:

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

浏览器机制

我们都知道了,浏览器是单线程解析javascript的,也就是说,我们的浏览器原理是是不能搞成异步的,因为就一个线程嘛,如何搞成异步的呢?这就需要模拟异步来实现了,主要需要setTimeout函数。

setTimeout和setInterval

setTImeout是指延迟指定的毫秒数后调用函数或计算表达式。看个例子

setTimeout(function(){alert("延迟一秒弹出")},1000);

setInterval方法可按照指定的周期(以毫秒计)来调用函数或计算表达式,就是一定时间之后重新执行一次,例子

setInterval(function(){alert("一秒弹一次")},1000);

对应的取消方法是clearTimeout和clearInterval,用法很简单。

用上面的两个方法模拟所谓的“异步调用”事实上是通过将代码段插入到代码的执行队列中实现的,因为javascript是单线程执行的,程序按序执行下来时,等浏览器有时间了就等一定的时间将setTimeout中的代码添加到执行队列中,通过例子说明吧

 setTimeout(function(){console.log("延迟一秒打印我")},1000);
console.log("打印出我");

当执行1行代码时,浏览器将里面的function(){console.log("延迟一秒打印我")}代码添加到了执行队列,并且延迟1秒之后执行,之后就到了第2行代码,打印了结果"打印出我",过了一秒之后打印出"延迟一秒打印我"。可以看出第1行代码执行了之后,并没有执行完,而是执行了第2行代码,1秒之后再执行setTimeout中的函数,就这样模拟异步函数调用,其实说白了并不是真正的异步函数调用,事实上所谓的异步只是一个假象,同样是运行在一个线程上。

假如现在在执行异步调用的时候,浏览器一直没有时间,那么就不用进行调用了,例子

 setTimeout(function(){console.log("延迟一秒打印我")},1000);
while(true){}//模拟一直很忙
console.log("打印出我");

上段代码啥都不会打印出来,因为代码function(){console.log("延迟一秒打印我")}插入之后,它要等1秒之后才能执行,但是浏览器一直都在忙,所以即使到了1秒钟之后,代码也不会被执行。

异步编程

一般来说,异步编程有四种方式,分别为回调函数方式,事件监听方式,发布-订阅方式和Promise方式,下面分别介绍这些方式。

回调函数

所谓回调函数,就是将函数作为参数传到需要回调的函数内部再执行,·例子,例如f1是很耗时的程序,f1执行完之后执行f2,如果是普通的这样

f1();
f2();

f2需要很长的时间才能执行,为了提高效率,我们使用回调函数的方式还模拟异步调用,这样f1(f2),怎样实现呢?其实就是利用setTimeout来实现

 function f1(func){
setTimeout(function(){
//f1代码
func();
},0);
}
function f2(){}
f1(f2);

自己弄个例子吧

function f1(func){
setTimeout(function(){
for(var i=0;i<10000;i++){
console.log(i);
}
func();
},0);
}
function f2(){
console.log("f2");
}
f1(f2);
console.log("程序末尾");

结果:程序末尾 1 2 ...10000 f2

程序f1执行结束之后执行f2,f1执行的时候不影响后面程序的执行,所以先显示“程序末尾”,然后是1.2.3.。。。。,最后是回调函数f2的结果。

ajax和nodejs主要就是通过回调函数这样方式实现的异步调用,简单介绍一下

ajax

 var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST","url", true);
xmlhttp.onreadystatechange = function(){
if(xmlhttp.readyState == 4){
if(xmlhttp.status == 200){
console.log(xmlhttp.responseXML);
}
}
}
xmlhttp.send();

nodejs

 fs.readdir(".", function (err, filenames) {
var i;
for (i = 0; i < filenames.length; i++) {
console.log(filenames[i]);
}
});

事件监听

javascript的事件驱动模式是重要的概念,代码的执行和顺序没有关系,而是与事件的何时发生有关系。javascript原生的绑定事件就是这个概念,例如

dom.onclick = function(){
console.log("click");
}

jquery就是类似这样的,都是事件绑定,这是演示,

function f2(){}
f1.on("complete",f2);
f1.trigger("complete");

订阅-发布

简单说:两种角色,订阅者和发布者,订阅者可以订阅事件,发布者发布事件消息,发布者发布消息只能通知到订阅改消息的订阅者,未订阅的不同接收到消息。专业解释:存在一个"信号中心",某个任务执行完成,就向信号中心"发布"(publish)一个信号,其他任务可以向信号中心"订阅"(subscribe)这个信号,从而知道什么时候自己可以开始执行。这就叫做"发布/订阅模式"(publish-subscribe pattern),又称"观察者模式"(observer pattern)。

自己弄个订阅-发布模式,大家看看,勿喷啊

 (function(window,undefined){
var topics = {};
var queue = {
publish : function(topic,args){
if(!topics[topic]){
return;
}
var funcs = topics[topic],
len = funcs.length;
for(var i=0;i<len;i++){
funcs[i](args);
}
return this;
},
subscribe :function(topic,func){
if(!topics[topic]){
topics[topic] = [];
}
topics[topic].push(func);
}
}
window.AllenQueue = queue;
})(window);

用法:

AllenQueue.subscribe("done",function(){console.log("done")});
AllenQueue.publish("done")

其实我觉得时间监听就是订阅发布模式,这两个应该是一样的,事件机制就是订阅发布的实例。

Promise

promise对象是CommonJS工作组提供的一种规范,用于异步编程的统一接口。promise对象通常实现一种then的方法,用来在注册状态发生改变时作为对应的回调函数。promise模式在任何时刻都处于以下三种状态之一:未完成(unfulfilled)、已完成(resolved)和拒绝(rejected)。以CommonJS Promise/A 标准为例,promise对象上的then方法负责添加针对已完成和拒绝状态下的处理函数。then方法会返回另一个promise对象,以便于形成promise管道,这种返回promise对象的方式能够支持开发人员把异步操作串联起来,如then(resolvedHandler, rejectedHandler)。resolvedHandler 回调函数在promise对象进入完成状态时会触发,并传递结果;rejectedHandler函数会在拒绝状态下调用。

Jquery在1.5的版本中引入了一个新的概念叫Deferred,就是CommonJS promise A标准的一种衍生。可以在jQuery中创建$.Deferref的对象。同时也对发送ajax请求以及数据类型有了新的修改,参考JQuery API。

例子如下

 function f1(){
    var dfd = $.Deferred();
    setTimeout(function () {
      // f1的任务代码
      dfd.resolve();
    }, 500);
    return dfd.promise;
}
f1().then(f2)

这个暂时就这样,以后我们会单独详细说说这个promise的。

小结

异步调用是javascript中一个重要的部分,我们还是要好好的掌握的。

【javascript 进阶】异步调用的更多相关文章

  1. ♫【异步】短小强悍的JavaScript异步调用库

    短小强悍的JavaScript异步调用库 var queue = function(funcs, scope) { (function next() { if(funcs.length > 0) ...

  2. 用Html5/CSS3做Winform,一步一步教你搭建CefSharp开发环境(附JavaScript异步调用C#例子,及全部源代码)上

    本文为鸡毛巾原创,原文地址:http://www.cnblogs.com/jimaojin/p/7077131.html,转载请注明 CefSharp说白了就是Chromium浏览器的嵌入式核心,我们 ...

  3. JavaScript进阶之高阶函数篇

    JavaScript进阶之高阶函数篇 简介:欢迎大家来到woo爷说前端:今天给你们带来的是JavaScript进阶的知识,接下来的系列都是围绕着JavaScript进阶进行阐述:首先我们第一篇讲的是高 ...

  4. JavaScript进阶内容——BOM详解

    JavaScript进阶内容--BOM详解 在上一篇文章中我们学习了DOM,接下来让我们先通过和DOM的对比来简单了解一下BOM 首先我们先来复习一下DOM: 文档对象模型 DOM把文档当作一个对象来 ...

  5. JavaScript进阶之路——认识和使用Promise,重构你的Js代码

    一转眼,这2015年上半年就过去了,差不多一个月没有写博客了,"罪过罪过"啊~~.进入了七月份,也就意味着我们上半年苦逼的单身生活结束了,从此刻起,我们要打起十二分的精神,开始下半 ...

  6. jquery ajax异步调用

    写程序的第一步都要知其然,至于知其所以然就要看个人的爱好了.下面说一下web开发中经常用的ajax. 这里是用的jquery框架实现的ajax异步调用.废话少说先上代码.(asp.net开发) var ...

  7. [置顶] Ajax程序:处理异步调用中的异常(使用Asp.Net Ajax内建的异常处理方法)

    无论在Window应用程序,还是Web应用程序以对用户友好的方式显示运行时的异常都是很有必要,尤其对于可能有很多不确定因素导致异常的Web应用程序;在传统的Web开发中,处理异常的方式——设计专门一个 ...

  8. JavaScript 进阶(一)JS的"多线程"

    这个系列的文章名为“JavaScript 进阶”,内容涉及JS中容易忽略但是很有用的,偏JS底层的,以及复杂项目中的JS的实践.主要来源于我几年的开发过程中遇到的问题.小弟第一次写博客,写的不好的地方 ...

  9. 漫话JavaScript与异步·第二话——Promise:一诺千金

    一.难以掌控的回调 我在第一话中介绍了异步的概念.事件循环.以及JS编程中可能的3种异步情况(用户交互.I/O.定时器).在编写异步操作代码时,最直接.也是每个JSer最先接触的写法一定是回调函数(c ...

随机推荐

  1. javascript原始数据类型compareto引用数据类型--近3天不太会的地方

    ECMAScirpt 变量有两种不同的数据类型:基本类型,引用类型.也有其他的叫法,比如原始类型和对象类型,拥有方法的类型和不能拥有方法的类型,还可以分为可变类型和不可变类型,其实这些叫法都是依据这两 ...

  2. python requests 模块初探

    现在经常需要在网页中获取相关内容. 其中无非获取网页返回状态,以及查看网页获取的内容几个方面,那么在这方面来看requests可能比urllib2库更简便一些. 比如:先用方法获取网页 r = req ...

  3. 和efast对接

    (1)    efast加入白名单 (2)    外网环境对接外网环境 内网环境对接内网环境 (3)    使用拉取的数据下单 才能同步到efast 4 档案同步 数据库 sys_ishop_sync ...

  4. 【并查集】【树】最近公共祖先LCA-Tarjan算法

    最近公共祖先LCA 双链BT 如果每个结点都有一个指针指向它的父结点,于是我们可以从任何一个结点出发,得到一个到达树根结点的单向链表.因此这个问题转换为两个单向链表的第一个公共结点(先分别遍历两个链表 ...

  5. Dubbo学习 概念定义

    Dubbo是什么? Dubbo[]是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案. 其核心部分包含: 远程通讯: 提供对多种基于长连接的NIO框架抽象封 ...

  6. OpenGL 4.5 Core Profile管线(GLSL与应用程序接口详解)【未完成】

    之前写过一篇博客,OpenGL管线(用经典管线代说着色器内部),说的主要是OpenGL的经典管线.大家都知道,现代OpenGL已经弃用(从OpenGL 3.0开始)经典管线功能(glBegin,变换矩 ...

  7. JS手札

    Node JS 关于JS调用 被调用:exports.cv=cv; cv为类,可以使用其方法cv.***: cv为函数名,可以使用其函数cv( , ): 调用: var cv=require(cv); ...

  8. IE8利用setCapture和releaseCapture解决iframe的拖拽事件

    最近有个需求须要实现左右拖拽功能,页面右边是个iframe页面,在chrome测试通过之后,发现在ie8上面效果不是很理想,最后查找资料得知可以使用ie自带的setCapture和releaseCap ...

  9. 电脑用miniDP链接显示器后电脑没声音

    今天用笔记本T440s miniDP 链接戴尔U2515显示器的 DP 连接后发现笔记本没声音了 原因: miniDP 不仅能支持视频传输还支持音频, 所以声音就改为从显示器发出了 但是我想让电脑输出 ...

  10. linux软连接和硬链接

    1.软连接(符号连接)创建方法(相当于windows的快捷方式) # ln -s 原文件 连接文件(最好使用绝对路径) 特点: 1.软连接文件是777的权限,而且很小很小: 2.可以跨分区(文件系统) ...