Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。
简单理解:
Promise顾名思义就是一个承诺,如果承诺兑现了,就做计划好的下一件事,如果没兑现就不继续做下一件事。(Romance in the code world)
Promise的几种状态
首先这种状态不收外界干扰,Proimse对象代表了一个异步操作。
状态1: pending (进行中)
状态2:fulfilled (已成功)
状态3:rejected(已失败)
改变promise的状态的方式只有一个,那就是异步的结果。promise对象一旦状态改变,就不会再变,任何时候都可以得到这个结果,它们相互转变的方式如下:
pending=>fulfilled
pending=>rejected
这两种状态一旦发生就无法再改变了,成为定性(resolved)。
文艺的话说就是,一旦错过,就再也无法挽回。请好好珍惜。哈哈哈。
简单的例子:
class POP {
toAn(data) {
return new Promise((resolve,reject)=>{
resolve();//第一遍
resolve();//第二遍
});
}
test(){
this.toAn({}).then(this.toK.bind(null,100));
}
toK(res){
console.log(res);
}
}
let pop=new POP();
pop.test();
你将看到如下输出(是的,只有一个):
100
Promise无法被取消
promise最大的缺点就是一旦创建就无法被取消,并且,如果未设置回调函数,它就会在内部抛出错误,但这种错误无法反应到外部,所以你不得而知。你甚至无法知道现在promise事件处理到哪个阶段,处理得怎么样了。resolve和reject函数的作用,resolve的作用是:pending=>resoved,reject的作用是:pending=>rejected
再来一个简单的例子
timeout(s){
return new Promise((resolve,reject)=>{
setTimeout(resolve,s*1000,"done");
});
}
....
let pop=new POP();
pop.timeout(2).then((v)=>{
console.log(v);
});
你将在2s后看到如下输出:
done
Promise 封装 Ajax
var toRequest=function (url) {
var promise=new Promise((resolve,reject)=>{
var client=new XMLHttpRequest();
client.open("GET",url);
client.onreadystatechange=handle;
client.responseType="json";
client.setRequestHeader("Accept","application/json");
client.send();
function handle() {
if(this.readyState!==4){
return;
}
if(this.status==200){
resolve(this.response);
}else{
reject(new Error(this.statusText));
}
}
});
return promise;
}
toRequest("http://localhost:8046/info").then((v)=>{
console.log(v);
})
</script>
我已经事先写好了/info接口,它将返回一个json;你将看到如下输出:
{ 若要捕获error,你应该这样
toRequest("http://localhost:8046/info").then((v)=>{
console.log(v);
}).catch((e)=>{
console.log(e);
});
}
上述例子中toRequest对XMLHttpRequest对象进行了封装,发出一个针对json数据的请求,并且返回一个promise对象,你将看到,在resolve和reject这两个函数中都携带了参数,前者成功返回数据后,将调用then(v=>{...}),其中v即使来自resolve的参数。它将返回一个respone。
all()
promise.all()方法用于将多个promise实例,包装成一个新的promise实例。
例如:
let promises=Promise.all([p1,p2,p3]...);
该方法接受一个数组作为参数,p1...p3..都是promise实例,如果不是,也会将参数转化成promise实例,在进行处理。当然该参数也可以不是数组,但必须含有Iterator接口(可序列)。
那么,他们之间的状态如何呢?
正如上面的例子,promises的状态同时由p1,p2,p3...决定。
他们间的关系如下图:
p1...p3的状态变为fulfilled,promies才会变为fulfilled
p1...p3的任何一个状态变为rejected,promies都会变为rejected
来一个简单的例子:
<script>
var toRequest=function (url) {
var promise=new Promise((resolve,reject)=>{
var client=new XMLHttpRequest();
client.open("GET",url);
client.onreadystatechange=handle;
client.responseType="json";
client.setRequestHeader("Accept","application/json");
client.send();
function handle() {
if(this.readyState!==4){
return;
}
if(this.status==200){
resolve(this.response);
}else{
reject(new Error(this.statusText));
}
}
});
return promise;
}
var promises=[1,2,3,4,5,6].map((page)=>{
return toRequest("http://localhost:8046/info?page="+page);
});
Promise.all(promises).then(values=>{
console.log(values);
}).catch((errors)=>{
console.log(errors);
})
</script>
你将看到如下的输出:
假设我停止了page等于4的相应又会如何呢?
你将看到如下输出:
关于Axios
看到这里,你应该隐隐约约感觉到了,上述的东西视乎似曾相识,这不就是axios吗?是的。没错,axios就是利用http method来进行数据的交互的,它厉害的地方在于它能将服务器交互的操作包装成promise实例交给前端处理。然后你就能轻而易举的处理他们了。
axios项目更多信息:https://www.kancloud.cn/yunye/axios/234845
至此,promise的基本应用已经over,如果你感兴趣你甚至可以拿他跟rxjs做一下比较,他们哪些部分可以互通,或者他们有什么相似之处呢?主要差别在哪里呢?有时间我们再做探讨吧,如果你从未接触过promise,那么赶紧试试应用到你的项目吧!
感谢关注~
圣诞快乐~