JS中的promise
promise对象用于表示一个异步操作的最终完成 (或失败),及其结果值。属于ES6语法中的内容。
用于处理异步问题。
单线程是js的痛点,因此,如何解决单线程问题,引用了异步的概念,用异步来模拟多线程的用法。其中ajax是典型的利用异步加载数据,实现数据刷新的案例。
但在处理多个有相互依赖关系的异步操作时,便会出现回调地狱。
//以ajax距离---回调地狱
ajax(function(){
ajax(function(){
ajax(function(){
ajax(function(){
})
})
})
})
极大的影响程序的运行,占用内存。
因此,promise提供了很好的解决方式,用于解决这些问题。
promise对象是一个代理对象(代理一个值),被代理的值在promise对象创建时可能是未知的。它允许为异步操作的成功和失败分别绑定相应的处理方法,但不是立即返回执行结果,而是返回成功或失败的状态。
语法new Promise( function(resolve, reject) {...}
promise有以下几种状态:
- pending:初始状态,既不是成功,也不是失败
- fulfilled:意味着操作成功
- rejected:意味着操作失败
then()方法
在初始状态时,promise对象可能变成fulfilled状态并返回一个相应的状态处理方法,也可能变成rejected状态并返回一个失败信息。当其中一种情况出现时,promise状态便不会改变,而是成为其中的一种状态,promise的then方法绑定的处理方法handlers便会被调用。其中then方法中绑定了两个参数:onfulfilled 和 onrejected,当返回的状态是fulfilled,调用onfulfilled方法,当返回的状态是rejected,调用onrejected方法。
在promise的语法中,new Promise( function(resolve, reject) {...}当promise被new创建时,会有resolve, reject这两个参数。其中当异步任务成功并返回结果值是,会调用resolve函数;而当异步任务失败并返回失败原因时,会调用reject函数。
以ajax为例:
function ajaxGet(url,data){
data = data || {};
var str = "";
for(var i in data){
str = str + i+"="+data[i]+"&";
}
var d = new Date();
url = url + "?" + str + "__htnt="+d.getTime();
var p = new Promise((resolve,reject)=>{
var xhr = new XMLHttpRequest();
xhr.open("get",url,true);
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
resolve(xhr.responseText);
}else if(xhr.readyState == 4 && xhr.status != 200){
reject(xhr.status)
}
}
xhr.send();
});
return p;
}
在这个ajax-get封装中,当传输成功时,则将成功后得到数据返回作为参数返回给resolve函数;当失败时,将失败状态作为参数返回给reject函数。
假设此时它有返回值,且 var p = ajaxGet(...)
p.then(function(data){
console.log("成功");
console.log('返回值为:',data);
},function(data){
console.log("失败");
console.log("错误代码:",data);
})
还可以在p.then(function(){})再加上.then(function(){}).then(function(){})
p.then(function(){
}).then(function(){
}).then(function(){
})...
可以将第一次异步得到的数据传到第一个then中,然后在将从第一个then中处理的数据进行第二次异步操作,并传递结果,依次往下传递。
catch()方法
添加一个拒绝(rejection)回调到当前 promise, 返回一个新的promise。只用来捕获失败状态。
finally()方法 --ES2018
finally添加一个事件处理回调与当前promise对象,并且在原promise对象解析完毕后,返回一个新的promise对象。无论结果是fulfilled或者是rejected,都会执行指定的回调函数。避免了同样的语句需要在then()和catch()中各写一次的情况。
all()方法
假设情况如下:
var p1 = ajaxGet(...);
var p2 = ajaxGet(...);
var p3 = ajaxGet(...);
Promise.all([p1,p2,p3]).then(function(res){
console.log(res);
},function(res){
console.log(res);
})
all()的参数应是一个数组。当在这个数组中所有的promise对象都成功才会触发成功,并把数组中所有promise返回值的数组作为成功回调的返回值,顺序与数组中一致。若有任一个对象失败。则会触发该primise对象的失败,并将第一个触发失败的promise对象的错误信息作为它的失败状态。
race()方法
all()是等所有的异步操作都执行完了再执行then()方法,那么race()方法就是相反的,谁先执行完成就先执行回调。
参考地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise