promise
概念:简单说promise就是一个容器,里面保存着某个未来才会结束的事件的结果,它可以获取异步操作的信息
三种状态(只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态,即—不受外界影响和不可逆):
- Pending(进行中)
- Resolved(已完成,又称 Fulfilled)
- Rejected(已失败)
//注意:promise是全部都成功时才成功,一个失败即失败
var p = new Promise(function(success,error){
//做一些异步操作
ajax / setTimeout
//成功的时候,执行的函数
success();
//失败的时候,执行的函数
error();
})
//定义成功和失败的状态要执行的代码
p.then(function(value){
console.log(value); //成功时调用
},function(value){
console.log(value); //失败时调用
})
传统的回调异步操作的缺点以及promise如何解决异步操作?
-
调用回调过早
- 对promise而言,即使是立即完成的promise也无法被同步观测到,也就是说一个promise调用then()的时候,即使这个promise已经决议了,提供给then的回调也总会被异步调用
-
调用回调过晚(或没有被调用)
- 对于一个promise对象注册每一个观察回调都是相对独立、互不相扰的。而promise对象调用都会被自动调用resolved()和reject()时,每个注册的观察回调也会被自动调用,所以这些观察回调的任意一个都无法影响或延误对其他回调的调用
- 而回调未调用,正常情况下,没有任何东西可以阻止promise想你通知它的决议,即使你的 js代码报错了,一会通过异常回调来获取到。如果Promise 永远不被决议的话, Promise 本身已提供了静态的抽象机制来作为解决方案
调用回调次数过少或过多
promise 的定义方式使得它只能被决议一次。即使代码中出现多次决议,这个 Promise 也会接受第一次决议,并会忽略掉其他任何后续调用。所以任何通过 then() 注册的回调只会被调用一次
-
未能传递所需的环境和参数
- 凡是被决议的值,都会被传递到观察回调中,如果没有显示的决议也会传递一个 undefined 给观察回调。需要主要的是,Promise 只允许传一个决意值,其他值会被默默忽略掉
-
吞掉可能出现的错误和异步
- 如果在创建 Promise 时,存在 JS 代码错误,会直接导致该 Promise 的拒绝决议,那么你可以通过 reject() 来获取异常,代码中的任何异常都不会吞掉。
Promise.all( ) 和 Promise.race( ) 的区别
- all会将传入的数组中的所有 Promise 全部决议以后,将决议值以数组的形式传入到观察回调中,任何一个 Promise决议为拒绝,那么就会调用拒绝回调
- 传递空数组时,all会立即决议,决议结果是 fullfilled, 值是 undefined
- race会将传入的数组中的所有 promise 中第一个决议的决议值传递给观察回调,即使决议结果是拒绝的。
- 传递空数组时,race会永远都不决议,程序卡死。。。
Promise是如何捕获异常的?与传统的 try / catch 相比有什么优势?
传统的 try / catch 捕获异常方式是无法捕获异步的异常的,代码如下
try{
setTimeout(function(){
undefined(); // undefined 不是一个方法,会抛出异常
},500)
} catch(err){
console.log(err)
}
try{
//有可能报错的语句
documnt.write("hello");
}catch(eve){ //try中的错误提示,ReferenceError: documnt is not defined
at promise.html:33
//报错之后,会执行这里的代码
console.log(eve);
}
console.log("world"); //world
而对于Promise对象来说,构造Promise实例时的代码如果出错,则会被认为是一个拒绝的决议,并会想观察回调中传递异常信息。所以即使是一个异步的请求,Promise也是可以捕获异常的,此外,Promise还可以通过 catch回调来捕获回调中的异常。
例:
var url1 = "xxxxxxxxxxxxx";
var url2 = "xxxxxxxxxxxxx";
var url3 = "xxxxxxxxxxxxx";
var p1 = ajax(url1);
var p2 = ajax(url2);
var p3 = ajax(url3);
var p = Promise.all([p1,p2,p3]);
p.then(function(res){
console.log(res);
},function(res){
console.log(res);
})
function ajax(url){
var p = Promise(function(success,error){
var ajax = new XMLHttpRequest();
ajax.open("post",url,true);
ajax.onreadystatechange = function(){
if(ajax.readyState == 4 && ajax.status == 200){
success(ajax.responseText);
}else if(ajax.readyState == 4 && ajax.status != 200){
error(ajax.status);
}
}
ajax.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
ajax.send("user=admin&pass=123");
});
return p;
}
如有侵权,请联系删除,谢谢