promise对于不信任问题的解决。
1、调用过早、调用过晚
以为promise的then是异步的,所以不论你调用早或者晚,状态改变的早或者晚,都要等这一轮宏任务完成后才能去执行微任务,去执行then。
2、回调未调用
1、首先,没有任何东西(包括错误)能阻止promise决议,如果你对promise注册了一个完成回调和一个拒绝回调,那么promise总会完成一个。
2、如果你完全不决议,我们也可以设置一些机制,比如用竟态超时;
function timeoutPromise(delay){
return new Promise(function(resolve,reject){
setTimeout(function(){
reject('timeout');
},delay);
});
}
Promise.race([foo(),timeoutPromise(3000)]);
这样就可以设置如果任务没有在规定时间完成,就发送一个错误信息
3、调用次数过多
由于promise的状态一旦决议,就无法更改,所以不会出现调用过多的情况。
4、未能传递参数/环境值
在promise中,最多只能有一个决议值,如果你没有显式决议,那么这个值就是undefined,如果要传递多个值,你可以把他们封装到数组或者对象中
5、吞掉错误或者异常
当你程序出现异常时,那么这个决议会被捕捉,使得这个决议被拒绝。
promise也没有摆脱回调
promise其实没有完全摆脱回调,他只是把改变了回调传递的位置我们只是从回调中获得一个状态。但是如何确定获得得状态稳定,值得信任呢,Promise.resolve().
Promise.resolve()
有时需要将现有对象转为 Promise 对象,Promise.resolve()方法就起到这个作用。
(1)参数是一个 Promise 实例
如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。
(2)参数是一个thenable对象
thenable对象指的是具有then方法的对象,比如下面这个对象。
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
Promise.resolve方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。
let thenable = {
then: function(resolve, reject) {
resolve(42);
}
};
let p1 = Promise.resolve(thenable);
p1.then(function(value) {
console.log(value); // 42
});
上面代码中,thenable对象的then方法执行后,对象p1的状态就变为resolved,从而立即执行最后那个then方法指定的回调函数,输出 42。
(3)参数不是具有then方法的对象,或根本就不是对象
如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的 Promise 对象,状态为resolved。
const p = Promise.resolve('Hello');
p.then(function (s){
console.log(s)
});
// Hello
上面代码生成一个新的 Promise 对象的实例p。由于字符串Hello不属于异步操作(判断方法是字符串对象不具有 then 方法),返回 Promise 实例的状态从一生成就是resolved,所以回调函数会立即执行。Promise.resolve方法的参数,会同时传给回调函数。
(4)不带有任何参数
Promise.resolve()方法允许调用时不带参数,直接返回一个resolved状态的 Promise 对象。
所以,如果希望得到一个 Promise 对象,比较方便的方法就是直接调用Promise.resolve()方法。
const p = Promise.resolve();
p.then(function () {
// ...
});
上面代码的变量p就是一个 Promise 对象。
需要注意的是,立即resolve()的 Promise 对象,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事件循环”的开始时。
setTimeout(function () {
console.log('three');
}, 0);
Promise.resolve().then(function () {
console.log('two');
});
console.log('one');
// one
// two
// three
上面代码中,setTimeout(fn, 0)在下一轮“事件循环”开始时执行,Promise.resolve()在本轮“事件循环”结束时执行,console.log(‘one’)则是立即执行,因此最先输出。
promise的一些局限
promise通常用来解决回调地狱的问题,但也有几个不可忽视的缺点
promise一旦新建就会立即执行,无法中途取消
当处于pending状态时,无法得知当前处于哪一个状态,是刚刚开始还是刚刚结束
如果不设置回调函数,promise内部的错误就无法反映到外部
promise封装ajax时,由于promise是异步任务,发送请求的三步会被延后到整个脚本同步代码执行完,并且将响应回调函数延迟到现有队列的最后,如果大量使用会大大降低了请求效率。