浅谈es6 promise
本文是借鉴于ac黄的博客。
接触es6也有几个月了,貌似没有系统的去学习过它,总是用到什么,查查什么。今天就说下es6中的promise对象。
先说说promise解决了什么问题?
写前端的同学都经常遇到这种问题:在多个接口异步请求数据,然后利用这些数据来进行一系列的操作。一般如下实现:
$.ajax({
url: '......',
success: function (data) {
//基于data,才能进行下发操作
$.ajax({
url: '......',
success: function (data) {
// ......
}
});
}
});
这样写会导致两个缺点:
在需要多个操作的时候,会导致多个回调函数嵌套,导致代码不够直观,就是常说的 Callback Hell。
如果几个异步操作之间并没有前后顺序之分(例如不需要前一个请求的结果作为后一个请求的参数)时,同样需要等待上一个操作完成再实行下一个操作。
es6中的Promise对象就来解决这个问题。
何为Promise对象?
一个 Promise 对象可以理解为一次将要执行的操作(常常被用于异步操作),使用了 Promise 对象之后可以用一种链式调用的方式来组织代码,让代码更加直观(解决第1项缺点)。而且由于 Promise.all
这样的方法存在,可以让同时执行多个操作变得简单(解决第2项缺点)。
resolve 和 reject
大家可以用把下方这段代码贴到浏览器开发模式中的console中运行,看看结果。
function helloWorld (ready) {
return new Promise(function (resolve, reject) {
if (ready) {
resolve("Hello World!");
} else {
reject("Good bye!");
}
});
} helloWorld(true).then(function (message) {
alert(message);
}, function (error) {
alert(error);
});
结果是,浏览器弹出 “hello world!”.
上面的代码实现的功能非常简单,helloWord
函数接受一个参数,如果为 true
就打印 "Hello World!",如果为 false
就打印错误的信息。helloWord
函数返回的是一个 Promise 对象。
在 Promise 对象当中有两个重要方法————resolve
和 reject
。
resolve
方法可以使 Promise 对象的状态改变成成功,同时传递一个参数用于后续成功后的操作,在这个例子当中就是 Hello World! 字符串。
reject
方法则是将 Promise 对象的状态改变为失败,同时将错误的信息传递到后续错误处理的操作。
Promise 对象有三种状态:
Fulfilled 可以理解为成功的状态
Rejected 可以理解为失败的状态
Pending 既不是 Fulfilld 也不是 Rejected 的状态,可以理解为 Promise 对象实例创建时候的初始状态
helloWorld 的例子中的 then
方法就是根据 Promise 对象的状态来确定执行的操作,resolve 时执行第一个函数(onFulfilled),reject 时执行第二个函数(onRejected)。
then 和 catch
then
helloWorld 的例子当中利用了 then(onFulfilld, onRejected)
方法来执行一个任务打印 "Hello World!",在多个任务的情况下 then
方法同样可以用一个清晰的方式完成。
例如:
function printHello (ready) {
return new Promise(function (resolve, reject) {
if (ready) {
resolve("Hello");
} else {
reject("Good bye!");
}
});
} function printWorld () {
alert("World");
} function printExclamation () {
alert("!");
} printHello(true)
.then(function(message){
alert(message);
})
.then(printWorld)
.then(printExclamation);
结果是顺序弹出:“Hello”“World”“!”
then
可以使用链式调用的写法原因在于,每一次执行该方法时总是会返回一个 Promise 对象。另外,在 then
onFulfilled 的函数当中的返回值,可以作为后续操作的参数。因此上面的方法可以写为:
function printHello (ready) {
return new Promise(function (resolve, reject) {
if (ready) {
resolve("Hello");
} else {
reject("Good bye!");
}
});
} printHello(true).then(function (message) {
return message;
}).then(function (message) {
return message + ' World';
}).then(function (message) {
return message + '!';
}).then(function (message) {
alert(message);
});
结果输出是:“Hello World!”。
catch
catch
方法是 then(onFulfilled, onRejected)
方法当中 onRejected
函数的一个简单的写法,也就是说可以写成 then(fn).catch(fn)
,相当于 then(fn).then(null, fn)
。使用 catch
的写法比一般的写法更加清晰明确。
Promise.all 和 Promise.race
Promise.all
可以接收一个元素为 Promise 对象的数组作为参数,当这个数组里面所有的 Promise 对象都变为 resolve 时,该方法才会返回。
var p1 = new Promise(function (resolve) {
setTimeout(function () {
resolve("Hello");
}, 3000);
}); var p2 = new Promise(function (resolve) {
setTimeout(function () {
resolve("World");
}, 1000);
}); Promise.all([p1, p2]).then(function (result) {
console.log(result); // ["Hello", "World"]
});
上面的例子模拟了传输两个数据需要不同的时长,虽然 p2 的速度比 p1 要快,但是 Promise.all
方法会按照数组里面的顺序将结果返回。
日常开发中经常会遇到这样的需求,在不同的接口请求数据然后拼合成自己所需的数据,通常这些接口之间没有关联(例如不需要前一个接口的数据作为后一个接口的参数),这个时候 Promise.all
方法就可以派上用场了。
Promise.race 和 Promise.all 方法类似,它同样接收一个数组,不同的是只要该数组中的 Promise 对象的状态发生变化(无论是 resolve 还是 reject)该方法都会返回。
兼容性
在浏览器端,一些主流的浏览器都已经可以使用 Promise 对象进行开发,在 Node.js 配合 babel 也可以很方便地使用。
如果要兼容旧的浏览器,建议可以寻找一些第三方的解决方案,例如 jQuery 的 $.Deferred。
最新文章
- 【新手出发】从搭虚拟机开始,一步一步在CentOS上跑起来.Net Core程序
- ASP.NET MVC 解析模板生成静态页一(RazorEngine)
- Sql Server参数化查询之where in和like实现详解
- WIN8 隐私声明
- The conversion of a varchar data type to a datetime data type resulted in an out-of-range value
- 缺陷跟踪系统Mantis Bug Tracker
- ansible 的组件inventory
- maven最齐全配置pom.xml
- appjs desktop2
- iOS程序的生命周期
- java学习笔记(11) —— Struts2与Spring的整合
- Linux系统VPS/服务器安装WINDOWS桌面环境可以采用的几个方法
- DIV上下居中
- java中public private protected default的区别
- 太原面经分享:如何在vue面试环节,展示你晋级阿里P6+的技术功底?
- MySQL数据库视图(view),视图定义、创建视图、修改视图
- [转]详解Oracle高级分组函数(ROLLUP, CUBE, GROUPING SETS)
- python 进行后端分页详细代码
- HDU-3507 Print Article (斜率优化)
- LINQ to SQL语句(1)Select查询的九种形式
热门文章
- mongodb配置复制集replset
- H264--3--NAL层的处理[6]
- POJ 3100:Root of the Problem
- 【Dairy】2016.10.17-1 OIer最悲剧的事情
- 第九周 Leetcode 502. IPO (HARD)
- UVaLive 6680 Join the Conversation (DP)
- PCB SI9000阻抗计算引擎Web方式实现方法
- Linux 上安装 Node.js
- bzoj 3390: [Usaco2004 Dec]Bad Cowtractors牛的报复【最大生成树】
- 添加jar到mvn私服