JavaScript语言将任务的执行模式可以分成两种:同步(Synchronous)和异步(Asychronous)

“同步模式”就是一个任务完成之后,后边跟着一个任务接着执行;程序的执行顺序和排列顺序是一直的;”异步模式”则完全不同,每一个任务都有一个或者多个回调函数(callback),前一个任务结束的时候,不是执行下一个任务,二十执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务顺序不一致的,异步的。

在浏览器端,耗时时间长的操作都应该异步执行,避免浏览器数去响应,最好的例子就是ajax操作。

在服务器端,“异步模式”甚至是唯一的模式,因为执行环境是单线程的,如果允许同步执行所有的http请求,服务器会急剧下降,很快会失去响应。

“异步模式”一共有4种方法,这4种方法可以写出结构更合理,性能更出色,维护更方便的js代码。这四种模式分别为:

一、回调函数(callback);

二、事件监听(Listener);

三、观察者模式;

四、promise对象

一、回调函数(callback)

异步的最基本的方法

假设有两个函数,f1和f2,后者等待前者执行结果。

f1();

f2();

如果f1是一个很耗时的任务,可以考虑改写f1,把f2写成f1的回调函数。

function f1(callback){
settimeout(function(){
//f1代码 },1000);
callback();  
}

执行代码变成下面的样子

f1(f2);

采用郑重方式,把同步操作变成了异步操作,f1不会堵塞程序的运行,先执行程序的主要逻辑,将耗时的操作推迟执行。

其实我理解起来也很费劲,因为上大学后第一门语言是c,然后是C++,再后来是java,在传统函数中以参数形式输入数据,并且使用返回语句返回值。理论上,在函数结尾处有一个return返回语句,结构上就是:一个输入点和一个输出点。函数的本质就是输入和输出之间实现过程的映射。

但是,当函数的实现过程很漫长,你选择等待函数处理完成之后处理,还是使用回调函数进行异步处理呢?

答:这种情况下,使用回调函数变得至关重要,例如:ajax请求。若是使用回调函数进行处理,艾玛就可以继续进行其他任务,而无需空等等。实际开发中,经常在JavaScript中使用异步调用,甚至在这里推荐使用。

//传递函数作为回调,函数作为参数传递
function fn(a,b,callback1){
var num=Math.ceil(Math.random()*(a-b)+b);
callback1(num); //传递结果
} fn(10,20,function(num){
console.log("随机数"+num);
}); //结果为10-20之间的随机数
function foo(){
var a=10;
return function(){
a*=2;
return a;
};
} var f=foo();
f(); //return 20
f(); //return 40
//返回一个内嵌匿名函数是创建闭包的方法。

ajax的一个回调函数例子。

$.ajax({
url:"test.json",
type:"GET",
data:{username:$("#username").val()},
dataType:"json",
beforSend:function(){
//禁用按钮防止重复提交
$("#submit").attr({disabled:"disabled"});
},
complete:function(msg){
//请求完成后调用的回调函数
},
error:function(msg){
//请求失败时被调用的回调函数
}
Success:function(msg){
//请求成功后调用的回调函数
}
});

(1)回调函数定义:函数A作为参数(函数引用)传递到另外一个函数B,并且这个函数B执行函数A,我们就叫函数A叫做回调函数,如果没有名称(函数表达式),我们就叫它匿名回调函数。

(2)回调函数优点:简单,容易理解和 部署。

缺点:不利于代码的阅读,和维护,各部分之间高度耦合,流程会很混乱,而且每一个任务只能指定一个回调函数。

二、事件监听

采用事件驱动模式。

任务的执行不取决代码的顺序,而取决于某一个事件是否发生。

监听函数有:on,bind,listen,addEventListener,observe

还是以f1和f2为例。首先,为f1绑定一个事件(采用jquery写法)。

f1.on('done',f2);

上面代码意思是,当f1发生done事件,就执行f2。

然后对f1进行改写:

function f1(){
settimeout(function(){
//f1的任务代码
f1.trigger('done');
},1000);
}

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

这种方法的优点:比较容易理解,可以绑定多个事件,每一个事件可以指定多个回调函数,而且可以去耦合,有利于实现模块化。

这种方法的缺点:整个程序都要变成事件驱动型,运行流程会变得不清晰。

事件监听方法:

(1)onclick方法

element.onclick=function(){
//处理函数
}

优点:写法兼容到主流浏览器

缺点:当同一个element元素绑定多个事件时,只有最后一个事件会被添加

例如:

element.onclick=handler1;
element.onclick=handler2;
element.onclick=handler3;

上诉只有handler3会被添加执行,所以我们使用另外一种方法添加事件

(2)attachEvent和addEvenListener方法

//IE:attachEvent
elment.attachEvent("onclick",handler1);
elment.attachEvent("onclick",handler2);
elment.attachEvent("onclick",handler3);

上述三个方法执行顺序:3-2-1;

//标准addEventListener
elment.addEvenListener("click",handler1,false);
elment.addEvenListener("click",handler2,false);
elment.addEvenListener("click",handler3,false);

执行顺序:1-2-3;

PS:该方法的第三个参数是泡沫获取,是一个布尔值:当为false时表示由里向外,true表示由外向里。

<div id="id1">
<div id="id2"></div>
</div> document.getElementById("id1").addEventListener("click",function(){console.log('id1');},false);
document.getElementById("id2").addEventListener("click",function(){console.log('id2');},false);
//点击id=id2的div,先在sonsole中输出,先输出id2,在输出id1 document.getElementById("id1").addEventListener("click",function(){console.log('id1');},false);
document.getElementById("id2").addEventListener("click",function(){console.log('id2');},true);
//点击id=id2的div,先在sonsole中国输出,先输出id1,在输出id2

 (三)DOM方法addEventListener()和removeListenner()

addEventListenner()和removeListenner()表示用来分配和删除事件的函数。这两种方法都需要三种参数,分别为:

string(事件名称),要触发事件的函数function,指定事件的处理函数的时期或者阶段(boolean)。

例子见(二)

(四)通用的时间添加方法:

on:function(elment,type,handler){
//添加事件
return element.attachEvent?elment.attachEvent("on"+type,handler):elment.addEventListener(type,handler,false);
}

冒泡事件和事件捕获区别,可以参考:http:/www.cnblogs.com/chengxs/p/6388779.html

三、观察者模式

观察者模式也叫发布订阅模式,它定义了一种一对多的关系,让多个观察者同时对监听某一个主题对象,这一个主题对象的状态变化就会通知多有的观察者对象,使得他们能够自动更新自己。

优点:1、支持简单的广播通信,自动通知所有已经订阅过的对象。

2、页面载入后,目标对象很容易与观察者存在一种动态关联,增加灵活性。

3、目标对象与观察者之间的抽象耦合关系能够单独扩展以及重用。

四、promise对象(promise 模式)

(1)promise对象是commonJS工作组提出的一种规范,一种模式,目的是为了异步编程提供统一接口。

(2)promise是一种模式,promise可以帮忙管理异步方式返回的代码。他讲代码进行封装并添加一个类似于事件处理的管理层。我们可以使用promise来注册代码,这些代码会在在promise成功或者失败后运行。

(3)promise完成之后,对应的代码也会执行。我们可以注册任意数量的函数再成功或者失败后运行,也可以在任何时候注册事件处理程序。

(4)promise有两种状态:1、等待(pending);2、完成(settled)。

promise会一直处于等待状态,直到它所包装的异步调用返回/超时/结束。

(5)这时候promise状态变成完成。完成状态分成两类:1、解决(resolved);2、拒绝(rejected)。

(6)promise解决(resolved):意味着顺利结束。promise拒绝(rejected)意味着没有顺利结束。

//promise
var p=new Promise(function(resolved))
//在这里进行处理。也许可以使用ajax setTimeout(function(){
var result=10*5;
if(result===50){
resolve(50);
}else{
reject(new Error('Bad Math'));
}
},1000);
}); p.then(function(result){
console.log('Resolve with a values of %d',result);
}); p.catch(function(){
console.error('Something went wrong');
});

(1)代码的 关键在于setTimeout()的调用。

(2)重要的是,他调用了函数resolve()和reject()。resolve()函数告诉promise用户promise已解决;reject()函数告诉promise用户promise未能顺利完成。

(3)另外还有一些使用了promise代码。注意then和catch用法,可以将他们想象成onsucess和onfailure事件的处理程序。

(4)巧妙地方是,我们将promise处理与状态分离。也就是说,我们可以调用p.then(或者p.catch)多少次都可以,不管promise是什么状态。

(5)promise是ECMAscript 6管理异步代码的标准方式,javascript库使用promise管理ajax,动画,和其他典型的异步交互。

简单的说,它的思想是:每一个异步任务返回一个promise对象,该对象有一个then方法,允许指定回调函数。比如,f1的回调函数f2,可以写成:

f1.then(f2);

f1要进行如下改写(使用jquery的实现):

function f1(){
var dfd=$.deferred();
settimeout(function(){
//f1的任务代码
dfd.resolve();
},500);
return dfd.promise;
}

这样写的优点:回调函数写成了链式写法,程序的流程可以看得很清楚,而且有一整套的配套方法,可以实现很多强大的功能。

比如,指定多个回调函数

f1().then(f2).then(f3);

再比如,指定发生的错误时的回调函数:

f1().then(f2).fail(f3);

而且,它有一个前面三种方法都没有的好处:如果一个任务已经完成,再添加回调函数,该回调函数会立即执行。

所以你不用担心错过某一个事件或者信号。

这种方法的缺点:编写和理解都相对比较难。

前端基本知识(四):JS的异步模式:1、回调函数;2、事件监听;3、观察者模式;4、promise对象的更多相关文章

  1. js中如何在不影响既有事件监听的前提下新增监听器

    一. 需求澄清 比如某个按钮已经绑定了2-3个对Window对象的load事件的监听,现在需要添加一个新的对click事件的监听器,但在一定条件下才会同时触发原有的2-3个load监听器,否则只触发新 ...

  2. SpringBoot事件监听机制及观察者模式/发布订阅模式

    目录 本篇要点 什么是观察者模式? 发布订阅模式是什么? Spring事件监听机制概述 SpringBoot事件监听 定义注册事件 注解方式 @EventListener定义监听器 实现Applica ...

  3. Ext JS 5的声明式事件监听

    在前文<在Ext JS 5使用ViewControllers>中,简单的介绍了Ext JS 5的一项重要改进——声明式事件监听.在本文,将深度探讨如何使用声明式事件监听啦简化应用程序的视图 ...

  4. JS的异步模式

    JS的异步模式:1.回调函数:2.事件监听:3.观察者模式:4.promise对象 JavaScript语言将任务的执行模式可以分成两种:同步(Synchronous)和异步(Asychronous) ...

  5. Node.js 教程 05 - EventEmitter(事件监听/发射器 )

    目录: 前言 Node.js事件驱动介绍 Node.js事件 注册并发射自定义Node.js事件 EventEmitter介绍 EventEmitter常用的API error事件 继承EventEm ...

  6. Mina、Netty、Twisted一起学(九):异步IO和回调函数

    用过JavaScript或者jQuery的同学都知道,JavaScript特别是jQuery中存在大量的回调函数,例如Ajax.jQuery的动画等. $.get(url, function() { ...

  7. JS之Callback function(回调函数)

    JS中的回调函数: 1.概念: 函数a有一个参数,这个参数是个函数b,当函数a执行完以后执行函数b,那么这个过程就叫回调,即把函数作为参数传入到另一个函数中,这个函数就是所谓的回调函数. 2.举例: ...

  8. React.js 小书 Lesson9 - 事件监听

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson9 转载请注明出处,保留原文链接和作者信息. 在 React.js 里面监听事件是很容易的事情 ...

  9. [JS]笔记12之事件机制--事件冒泡和捕获--事件监听--阻止事件传播

    -->事件冒泡和捕获-->事件监听-->阻止事件传播 一.事件冒泡和捕获 1.概念:当给子元素和父元素定义了相同的事件,比如都定义了onclick事件,点击子元素时,父元素的oncl ...

随机推荐

  1. 2.5. Integer 16 、Integer 32、Integer 64(Core Data 应用程序实践指南)

    Core Data 使用 “带符号的整数”,通常我们会选择Integer 32,如果不够,可以升级为Integer 64 (第3章),通过升级托管对象模型. 这三种类型对应的特性(Property)类 ...

  2. js原生之设计模式开篇介绍

    本文主要讲述一下,什么是设计模式(Design pattern),作为敲键盘的我们要如何学习设计模式.设计模式真的是一把万能钥匙么?     各个代码的设计模式几乎每个人都知晓,就算不会那也一定在一些 ...

  3. Win10下CISCO VPN Client无法安装解决方案

    Cisco vpn client 在Windows升级到Windows 10 之后无法正常安装使用,在这种情况下:1.先安装Dell SonicWALL Global VPN Client(GVCSe ...

  4. 大型网站制作前端使用PHP后台逻辑用 Java

    对于网站团队,大概可以按照职责分为前端.后端.架构三种角色. 前端:负责所有和用户有交互的产品,包括 WEB以及手机客户端 后端:负责各种业务 API 的开发,以及服务器端其他系统的开发 架构:负责设 ...

  5. JSP userBean setProperty直接从request中获取参数

    JSP userBean setProperty直接从request中获取参数: form表单Jsp: <%@ page language="java" import=&qu ...

  6. Docker环境中部署DzzOffice 1.2.5.2

    整体思路: 1.官方获取mysql.php+apache镜像: 2.基于php+apache,创建DzzOffice镜像: 3.启动mysql镜像: 4.启动DzzOffice镜像,链接mysql镜像 ...

  7. python yield generator 详解

    本文将由浅入深详细介绍yield以及generator,包括以下内容:什么generator,生成generator的方法,generator的特点,generator基础及高级应用场景,genera ...

  8. fir.im Weekly - 2017 年必须了解的 iOS 开源库

    放假的脚步临近,每个人都在期待一个愉悦的春节假期.最近,@张嘉夫 分享了一篇 Medium 上的文章<33 个 2017 年必须了解的 iOS 开源库>,总结了 2016 年最棒的 iOS ...

  9. POJ1088(dp)

    滑雪 Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 91574   Accepted: 34573 Description ...

  10. JS中常见排序算法详解

    本文将详细介绍在JavaScript中算法的用法,配合动图生动形象的让你以最快的方法学习算法的原理以及在需求场景中的用途. 有句话怎么说来着: 雷锋推倒雷峰塔,Java implements Java ...