写点什么

Node.js 异步编程之 Promise

  • 2022 年 7 月 12 日
  • 本文字数:2423 字

    阅读完需:约 8 分钟

前言

先来介绍一下 Promise 是什么?


Promise:


  • 当前事件循环得不到的结果,但未来的事件循环会给到你结果

  • 是一个状态机

  • pending------还没有得到结果

  • fulfilled/resolved------得到了一个正确的结果

  • rejected------得到了一个错误的结果


从代码入手👻

(function(){    var promise = new Promise(function(resolve,reject){        setTimeout(()=>{            resolve();// reject(new Error());        },500)    })        console.log(promise);        setTimeout(()=>{        console.log(promise);    },800)})();
复制代码


这是一个从 pending 到 resolved/rejected 的过程。


那么可能有的小伙伴会想,我可不可以让他在 300 毫秒的时候转变成 resolve 的状态,在 500 毫秒的时候从 resolved 转变成 rejected 状态呢?那我们来实际操作一下看看结果吧。


我也有这样的疑惑


(function(){    var promise = new Promise(function(resolve,reject){        setTimeout(()=>{            resolve();        },300)        setTimeout(()=>{            reject(new Error());        },300)    })        console.log(promise);        setTimeout(()=>{        console.log(promise);    },800)})();
复制代码



从结果我们可以看到,他还是 fulfilled 状态,也就是 resolved 状态,没有改变。


所以在 resolved 状态与 rejected 状态之间应该是不能转换的。

继续学习🐸

我们使用 promise 去解决异步问题,是希望他拿到结果之后就要立即通知我们,那这个时候我们要怎么去写呢?


我们可以借助 promise 下的一个方法,叫做 then


把上面的代码进行改写


(function(){    var promise = new Promise(function(resolve,reject){        setTimeout(()=>{            resolve(3);        },300)    }).then(function(res){      console.log(res)    }).catch(function(){        })        console.log(promise);        setTimeout(()=>{        console.log(promise);    },800)})();
复制代码


可能有小伙伴注意到了,我们上面还多了一个 catch 方法,没错,他在这里也是用来处理 error 的,而 error 在 promise 里就对应着 rejected 状态了,将上面的代码再改点东西,就成了这样子。


(function(){    var promise = new Promise(function(resolve,reject){        setTimeout(()=>{            reject(new Error());        },300)    }).then(function(res){      console.log(res)    }).catch(function(err){        console.log(err)    })        console.log(promise);        setTimeout(()=>{        console.log(promise);    },800)})();
复制代码


  • 关于.then 和.catch

  • resolved 状态的 promise 会回调后面的第一个.then

  • rejected 状态的 promise 会回调后面的第一个.catch

  • 任何一个 rejected 状态且后面没有.catch 的 promise,都会造成浏览器/node 环境的全局错误

为什么说 promise 优秀呢?

他可以解决异步流程控制的问题(这个在前面 callback 那节笔记有记过,[可以去看一下](Node.js学习笔记之异步编程部分(一) | Wangez-Blog))。


还是之前面试的问题,这次我们用 promise 的思路来看一下


(function(){    var promise = interview();    promise    .then((res)=>{        console.log('smile');    })    .catch((err)=>{        console.log('cry')    })
})();

function interview(){ return new Promise((resolve,reject)=>{ setTimeout(()=>{ if(Math.random()>0.2){ resolve('success') }else{ reject(new Error('fail')); } },500) })}
复制代码

小细节,拿笔记好📢

执行 then 和 catch 会返回一个新的 promise,该 promise 最终状态根据 then 和 catch 的回调函数的执行结果决定


  • 如果回调函数是 throw,那么 promise 就是 rejected 状态

  • 如果回调函数是 return,那么 promise 就是 resolved 状态

  • 但如果回调函数最终 return 了一个 promise,该 promise 回跟回调函数 return 的那个 promise 状态保持一致。


接下来用多轮面试的例子,来演示一下:


(function(){    var promise = interview();    promise    .then((res)=>{        return interview(2)    })    .then(()=>{        return interview(3)    })    .then(()=>{        console.log('smile');    })    .catch((err)=>{        console.log('cry at  ' + err.round + '  round');    })
})();

function interview(round){ return new Promise((resolve,reject)=>{ setTimeout(()=>{ if(Math.random()>0.2){ resolve('success') }else{ var error = new Error('fail'); error.round = round reject(error); } },500) })}
复制代码


想知道你在第几轮面试挂了吗?去执行一下试试吧!

小优化🎁

我们肯定是同时面试多家公司的呀,那我们再给上面的代码做一些优化吧。


(function(){    Promise    .all([        interview('tencent'),        interview('Ali88')    ])    .then(()=>{        console.log('smile');    })    .catch((err)=>{        console.log('cry for  ' + err.name );    })
})();

function interview(name){ return new Promise((resolve,reject)=>{ setTimeout(()=>{ if(Math.random()>0.2){ resolve('success') }else{ var error = new Error('fail'); error.name = name reject(error); } },500) })}
复制代码


注意:


  • catch 只能返回第一个面试挂的公司,如果都想知道就要存好所有的 promise 的状态并且打印出来哦。

最后

总觉得上面那个例子,面试通过一家,第二家挂了他会给我返回到 catch 里面去呢,可以在继续研究一下。

发布于: 刚刚阅读数: 4
用户头像

公众号:前端成长日记 2021.08.09 加入

还未添加个人简介

评论

发布
暂无评论
Node.js异步编程之Promise_7月月更_是乃德也是Ned_InfoQ写作社区