深入理解JS异步编程三(promise)
jQuery
原本写一个小动画我们可能是这样的
$('.animateEle').animate({
opacity:'.5'
}, 4000,function(){
$('.animateEle2').animate({
width:'100px'
},2000,function(){
$('.animateEle3').animate({
height:'0'
},2000);
});
});
但是如果我们使用promis对象的话,就可以使得代码更加简单易懂
var animate1 = function() {
return $('.animateEle1').animate({opacity:'.5'},4000).promise();
};
var animate2 = function() {
return $('.animateEle2').animate({width:'100px'},2000).promise();
};
var animate3 = function(){
return $('.animateEle3').animate({height:'0'},2000).promise();
};
$.when(animate1()).then(animate2).then(animate3);
对比上面两段代码,回调的形式相比promise,后期较难维护,层层嵌套,出错不好定位,反直觉。
Promise对象方法
对于DOM,动画,ajax相关方法,都可以使用 promise 方法。调用 promise 方法,返回的是 promise 对象。可以链式调用 promise 方法。
比如jquery中的ajax的 $.post $.get $.ajax 等方法,实际上都是默认调用了promise方法,然后返回了一个promise对象
promise对象常见的方法有三个 : done , fail , then 。
$.get('/',{}).done(function(data){
console.log('success');
}).fail(function(){
console.log('fail');
});
query 这里的接口方法太多了,就跟早期的事件方法绑定一样, live , delegate , bind ,最终还是归为 on。
deferred对象方法
var promisepbj = new $.Deferred();
promisepbj.done(function() {
console.log('haha,done');
}).fail(function() {
console.log('失败了');
}).always(function(res) {
console.log('我总是被执行啦');
});
//使用resolve或者reject就可以调用defferred对象了
promisepobj.resolve();
//promisepobj.reject();
resolve 方法会触发 done 的回调执行, reject 会触发 fail 的回调,对于 always 方法,deferred 对象,无论是 resolve 还是 reject ,都会触发该方法的回调。
ES6 Promise
前面讲了很多jquery的promise实现,$.Deferred 和 ES2015 的 Promise 是不同的东西,因为前者不符合 Promises/A+ 规范。 Promise 对象在 EMCAScript 2015 当中已经成为标准。现在要来谈谈马上要成为主流趋势的es6原生promise对象,首先贴一个很详细的es6 promise的小书,基本你知道的不知道都在里面 http://liubin.org/promises-book/#introduction。
阮一峰大神的关于ES6的promise解释 http://es6.ruanyifeng.com/#docs/promise。
定义
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
特点:
- 有三种状态:Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)。
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,会一直保持这个结果。就算改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
var promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
then方法
then方法可以接受两个回调函数作为参数。第一个回调函数是Promise对象的状态变为Resolved时调用,第二个回调函数是Promise对象的状态变为Reject时调用。其中,第二个函数是可选的,不一定要提供。这两个函数都接受Promise对象传出的值作为参数。
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, 'done');
});
}
timeout(100).then((value) => {
console.log(value);
});
异常处理
异常处理一直是回调的难题,而promise提供了非常方便的catch方法:在一次promise调用中,任何的环节发生reject,都可以在最终的catch中捕获到:
Promise.resolve().then(function(){
return loadImage(img1);
}).then(function(){
return loadImage(img2);
}).then(function(){
return loadImage(img3);
}).catch(function(err){
//错误处理
})
基本的 api
- Promise.resolve()
- Promise.reject()
- Promise.prototype.then()
- Promise.prototype.catch()
- Promise.all()
- Promise.race()
具体的很多的用法可以参考阮一峰的 http://es6.ruanyifeng.com/#docs/promise 入门教程
深入理解JS异步编程三(promise)的更多相关文章
- JS异步编程 (2) - Promise、Generator、async/await
JS异步编程 (2) - Promise.Generator.async/await 上篇文章我们讲了下JS异步编程的相关知识,比如什么是异步,为什么要使用异步编程以及在浏览器中JS如何实现异步的.最 ...
- 理解js异步编程
Promise 背景 javascript语言的一大特点就是单线程,在某个特定的时刻只有特定的代码能够被执行,并阻塞其它的代码,也就是说,同一个时间只能做一件事. 怎么做到异步编程?回调函数.直到no ...
- 深入理解JS异步编程五(脚本异步加载)
异步脚本加载 阻塞性脚本 JavaScript在浏览器中被解析和执行时具有阻塞的特性,也就是说,当JavaScript代码执行时,页面的解析.渲染以及其他资源的下载都要停下来等待脚本执行完毕 浏览器是 ...
- 深入理解JS异步编程四(HTML5 Web Worker)
>Web Workers 是 HTML5 提供的一个javascript多线程解决方案,我们可以将一些大计算量的代码交由web Worker运行而不冻结用户界面. 一:如何使用Worker We ...
- 深入理解JS异步编程(一)
js事件概念 异步回调 首先了讲讲js中 两个方法 setTimeout()和 setInterval() 定义和用法: setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式. 语法 ...
- 深入理解JS异步编程二(分布式事件)
PubSub模式 从原生的js角度,我们要监听某事件的方法就是利用addEventListener方法,但是当我们的页面趋于复杂,比如要向某个元素添加多个处理事件,那么就要用一个封装函数汇集多个处理函 ...
- 一个例子读懂 JS 异步编程: Callback / Promise / Generator / Async
JS异步编程实践理解 回顾JS异步编程方法的发展,主要有以下几种方式: Callback Promise Generator Async 需求 显示购物车商品列表的页面,用户可以勾选想要删除商品(单选 ...
- node.js异步编程解决方案之Promise用法
node.js异步编程解决方案之Promise var dbBase = require('../db/db_base'); var school_info_db = require('../db/s ...
- js异步编程
前言 以一个煮饭的例子开始,例如有三件事,A是买菜.B是买肉.C是洗米,最终的结果是为了煮一餐饭.为了最后一餐饭,可以三件事一起做,也可以轮流做,也可能C需要最后做(等A.B做完),这三件事是相关的, ...
随机推荐
- 如何编译spring源码,并导入到eclipse中
wsc@WSC-PC /d/wsc/study-spring-source$ git clone https://github.com/spring-projects/spring-framework ...
- 团队开发——冲刺2.d
冲刺阶段二(第四天) 1.昨天做了什么? 把收集的图标进行统一整理,使用相同风格.类型,使界面更加美观. 2.今天准备做什么? 开始写测试计划书. 3.遇到什么困难? 关于昨天遇到的问题:在游戏界面加 ...
- 转 TextBox的EnableViewState属性问题
问题如下: ---------------------------------------------------------------------------------------------- ...
- Appium 解决不能输入中文字符问题
只需在初始化driver方法时,写这两行代码即可: capabilities.setCapability("unicodeKeyboard", "True" ...
- codeforces194a
link:http://codeforces.com/contest/334/problem/A 很有意思的一道构造题.发现CF上经常出这种不难但是很不错的构造题. #include <iost ...
- OS实验一实验报告
实验一.命令解释程序的编写实验 专业:商业软件工程 姓名:王泽锴 学号:201406114113 一.实验目的 (1)掌握命令解释程序的原理: (2)*掌握简单的DOS调用方法: (3)掌握C语 ...
- Squid configuration directives 3.0
WELCOME TO SQUID 3.0.STABLE25-20100412 ---------------------------- This is the default Squid config ...
- QTreeWidget创建
QTreeWidget.顾名思义,这个类用来展示树型结构.同前面说的QListWidget类似,这个类需要同另外一个辅助类QTreeWidgetItem一同使用.不过,既然是提供方面的封装类,即便是看 ...
- C#中get和set的写法
class program{ private string name; public string XXXXXX{ get{return name;} set{name=value;} } } 在C# ...
- c++读写二进制文件
要读取文件必须包含<fstream>头文件,这里包含了C++读写文件的方法,可以使用fstream 类,这个类可以对文件进行读写操作. 1.打开文件. 打开文件可以有两种方式,第一 ...