聊聊 Promise 你不会注意的点

前言

前一篇文章梳理了promise的基础聊聊promise系列(基础)promise

这篇文章将从容易出现错误的几种用法出发,得出如何去正确的用promise。bash

如何避免promise的回调地狱

想必你们在项目中会见过这样的写法。函数

const p1 = new promise((resolve, reject) => {
    resolve(true);
})
p1.then((res) => {
    if(res) {
        const p2 = new promise((resolve, reject) => {
            resolve(true);
        })
        p2.then((res) => {
            const p3 = new promise((resolve, reject) => {
                resolve(true);
            })
        })
    }
})
复制代码

这个写法写出了回调地狱的感受。那如何优化他呢!!post

const p1 = new promise((resolve, reject) => {
    resolve(true);
})
const p2 = new promise((resolve, reject) => {
    resolve(true);
})
const p3 = new promise((resolve, reject) => {
    resolve(true);
})
p1.then((res) => {
    if(res) {
        return p2
    }
}).then((res) => {
    if(res) {
        return p3
    }
})
复制代码

用这种链式调用的方式仍是十分的优雅的。优化

catch() 与 then(null, ...) 并不是彻底等价

举个等价的例子:ui

Promise.reject('error').catch((res) => {
    console.log(res);
})
Promise.reject('error').then(null, (res) => {
    console.log(res);
})
复制代码

catch是用then(null, ...)来实现的,可是在某些条件下,并非等价的,好比如下例子:spa

const p1 = new Promise((resolve, reject) => {
    if(/*正确的条件*/) {
        resolve('success');
    } else {
        reject('false');
    }
});
//用法一:
p1.then((res) => {
    console.log(res);
    throw new Error('我在then出错了');
}, (res) => {
    console.log(res);
});
//用法二:
p1.then((res) => {
    console.log(res);
    throw new Error('我在then出错了');
}).catch((res) => {
    console.log(res);
})
复制代码
上述例子的区别就在与,catch能够捕捉then中发生的错误,可是then的第二个回调函数捕捉不了第一个参数中的报错。
复制代码

输出的结果:3d

避免promise穿透问题

什么是promise穿透问题呢?举个例子:code

Promise.resolve('foo').then(Promise.resolve('bar')).then(function (result) {
  console.log(result);
});
复制代码

这个鬼东西会输出啥??cdn

斟酌良久,你可能回答bar,那你就错了,实际输出的是foo。

由于then中但愿得到的是一个函数。而当你传入一个promise的时候,至关于then(null),不管你添加多少个then(null),promise都会穿透到下一个。

固然,对于上述例子,你可能但愿的是这样作:

Promise.resolve('foo').then(() => {
    return Promise.resolve('bar');
}).then(function (result) {
  console.log(result);
});
复制代码

切记,必定要往then里面传入函数

几种不一样的写法带来的后果

接下来,咱们经过一个例子,来看一下不一样写法带来的后果。

const func = function(last, num) {
  return new Promise((resolve, reject)=>{
      console.log(last, num);
      resolve(num);
  });
};

// 写法一
Promise.resolve()
  .then((last)=>{return func(last, 1);})
  .then((last)=>{return func(last, 2);})
  .then((last)=>{return func(last, 3);});

// 写法二
Promise.resolve()
  .then((last)=>{func(last, 1);})
  .then((last)=>{func(last, 2);})
  .then((last)=>{func(last, 3);});
  
 // 写法三
Promise.resolve()
  .then(func(undefined, 1))
  .then(func(undefined, 2))
  .then(func(undefined, 3));
  
 // 写法四
func(undefined, 1).then(func(undefined, 2)).then(func(undefined, 3));
复制代码
  • 写法一

结果:

undefined 1
1 2
2 3
复制代码

这是咱们想要的结果,也是promise链式调用正确的写法。

  • 写法二 结果:
undefined 1
undefined 2
undefined 3
复制代码

虽然在then中执行了函数,可是并无return有结果的promise给下一个then,因此后面的then永远是收不到结果值的。

  • 写法三

结果:

undefined 1
undefined 2
undefined 3
复制代码

这种写法是形成promise穿透引发的。then里面须要是一个函数,可是却传了一个promise进去。

  • 写法四

结果:

undefined 1
undefined 2
undefined 3
复制代码

和第三种也发一致,也是promise穿透,then里面须要是一个函数,可是却传了一个promise进去。

相关文章
相关标签/搜索