JS异步之Promise解决信任问题(一)

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是异步任务,发送请求的三步会被延后到整个脚本同步代码执行完,并且将响应回调函数延迟到现有队列的最后,如果大量使用会大大降低了请求效率。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值