浅谈promise对象
背景:
最近项目在做小程序的开发,涉及设计一个统一的登录公共方法,当实现时涉及到多个异步请求,那么问题来了,如何让多个异步请求先后同步进行呢?很多人会想到使用多层嵌套套来实现,就像这样:
function fun1() {
fun2() {
fun3() {
fun4() {
}
}
}
}
可是嵌套难以维护而且耦合性很高、不方便。
苦寻百度,最后找到Promise,Promise就是这样一个专门解决多个异步请求问题的对象。
Promise
介绍
Promise是异步编程的一种解决方案,由社区提出,经ES6规范了标准,因此原生提供Promise。在浏览器中输入以下语句,看是否支持Promise,当然也可以使用Can I Use查一查兼容性
'use strict';//严格模式
new Promise(function () {});
理解
先从最基本的案例去了解一下Promise的用法。首先是基本嵌套使用:
//嵌套调用
function fun1() {
console.log('执行fun1');
//设置时间把fun1看作为异步方法
setTimeout(function() {
//...fun1执行完毕
fun2();
},2000);
}
function fun2() {
console.log('执行fun2');
}
fun1();
结果:
执行fun1
执行fun2
为了保证fun1执行完再调用fun2,一般我们会使用嵌套调用,待fun1完全执行再调用fun2。那Promise是怎样的思路呢?
function fun1() {
return new Promise(function(resolve,reject) {
console.log('执行fun1');
//设置时间把fun1看作为异步方法
setTimeout(function() {
//...fun1执行完毕
resolve();
},2000);
});
}
function fun2() {
console.log('执行fun2');
}
fun1().then(function(res) {
fun2();
}).catch(function(res) {
console.log("出错了");
});
结果:
执行fun1
执行fun2
当使用Promise解决异步时,思路会不一样,它是把未来结束的结果暴露出去(resolve),那么我们就可以继续同步(then)执行我们接下想做的事情(fun2),这就是Promise解决异步编程的基本思路。
概括来说,Promise对象就是一个容器(对象)包含了一些未来会结束的事件的结果。
特点
Promise包含了三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。而且只能从pending->fulfilled或者pending->和rejected,理解起来如下图:
常规用法
在帮公司写小程序时,总结出一个比较通用的Demo解决异步编程问题:
function fun1() {
return new Promise((resolve, reject) => {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
}
function fun2() {
return new Promise((resolve, reject) => {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
}
fun1().then(function (res) {
return fun2();
if (/*需要中止*/) {
var res = {'code':0};
return Promise.reject();//通过reject直接跳到catch
}
}).then(function (res) {
//最后的事情...
}).catch(function (res) {
if (res.code != 0) {
//错误时执行的代码
}
});
首先我们定义一个异步方法,一般方法都会有两个状态成功和失败,比如ajax,那么我们可以成功是执行resolve,失败时执行reject,这样我们通过结果来操作下一步。
那好啦,接着我们写方法的整体流程,通过then和catch方法来捕捉方法执行后的结果。then方法可以保证代码顺序地执行,应该可以有多个;而catch一个就够了,就是用来捕捉错误(有点像try...catch),但是还有另外一种用法,就是通过在then中写如上的代码,就可以达到中止的效果,我的思路就是通过reject一个code到catch中,这样就可以判断到底你是中止还是错误了。