如何在Promise链中共享变量?
来源:互联网 发布:bw报表软件 编辑:程序博客网 时间:2024/06/08 16:56
译者按: 使用Promise写过异步代码的话,会发现在Promise链中共享变量是一个非常头疼的问题,这也是Async/Await胜过Promise的一点,我们在Async/Await替代Promise的6个理由有提过,这篇博客将有更详细的介绍。
- 原文: Passing data between Promise callbacks
- 译者: Fundebug
为了保证可读性,本文采用意译而非直译,并且对源代码进行了大量修改。另外,本文版权归原作者所有,翻译仅用于学习。
基于Promise编写异步代码时,通常会使用多个then组成链式调用,每一个then都会有一个回调函数。因此,在Promise链中,会有很多回调函数,每个回调函数都有一个独立的变量作用域。那么,如何在这些回调函数之间共享变量呢?这篇博客将探讨这个问题。
问题
connection变量在A处定义,在B和C处都需要使用。但是,由于A、B、C处于各自独立的作用域,connection变量将不能在B和C处直接使用。
db.open() .then(connection => // A { return connection.select( { name: 'Fundebug' }); }) .then(result => { connection.query(); // B }) .catch(error => { // ... }) .finally(() => { connection.close(); // C });
方法1:使用高阶作用域变量
在更高阶的作用域定义connection变量,在D处赋值,这样在B和C处直接使用了。
let connection; // Adb.open() .then(conn => { connection = conn; // D return connection.select( { name: 'Fundebug' }); }) .then(result => { connection.query(); // B }) .catch(error => { // ... }) .finally(() => { connection.close(); // C });
问题:如果需要共享的变量过多(这是很常见的情况),则需要在高阶作用域中定义很多变量,这样非常麻烦,代码也比较冗余。
方法2:嵌套作用域
将需要使用connection变量的Promise链内嵌到对应then回调函数中,这样在B和C处直接使用了。
db.open() .then(connection => // A { return connection.select( { name: 'Fundebug' }) .then(result => { connection.query(); // B }) .catch(error => { // ... }) .finally(() => { connection.close(); // C }); });
问题:之所以使用Promise,就是为了避免回调地域,将多层嵌套的回调函数转化为链式的then调用;如果为了共享变量采用嵌套写法,则要Promise有何用?
方法3:return多个值
intermediate变量在A处定义并赋值,而在B处需要使用;但是,由于A与B处于不同的作用域,B出并不能直接使用intermediate变量:
return asyncFunc1() .then(result1 => { const intermediate = ··· ; // A return asyncFunc2(); }) .then(result2 => { console.log(intermediate); // B });
在A处使用Promise.all返回多个值,就可以将intermediate变量的值传递到B处:
return asyncFunc1() .then(result1 => { const intermediate = ···; return Promise.all([asyncFunc2(), intermediate]); // A }) .then(([result2, intermediate]) => { console.log(intermediate); // B });
问题: 使用Promise.all用于传递共享变量,看似巧妙,但是有点大材小用,并不合理;不能将变量传递到.catch()与finally()中;当共享变量过多,或者需要跨过数个.then(),需要return的值会很多。
方法4: 使用Async/Await
Async/Await是写异步代码的新方式,可以替代Promise,它使得异步代码看起来像同步代码,可以将多个异步操作写在同一个作用域中,这样就不存在传递共享变量的问题了!!!
方法1中的示例可以改写为:
try{ var connection = await db.open(); // A const result = await connection.select( { name: 'Fundebug' }); connection.query(); // B}catch (error){ // ...}finally{ connection.close(); // C}
方法3中的示例可以改写为:try{ result1 = await asyncFunc1(); const intermediate = ··· ; result2 = await asyncFunc2(); console.log(intermediate);}catch (error){ // ...}
毋庸赘言,Async/Await直接将问题消灭了,无疑是更好的方式!
参考
- Promises for asynchronous programming
- ES proposal: Promise.prototype.finally()
- ES proposal: Promise.try()
- Async/Await替代Promise的6个理由
版权声明:
转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/09/04/promise-share-variable/
- 如何在Promise链中共享变量?
- 在Angular中使用promise
- 如何在OpenSolaris中共享桌面
- 如何在模块中共享数据
- 如何在Exe和BPL插件中实现公共变量共享及窗口溶入技术Demo源码
- 快速将 Promise 运用在开发中
- Javascript 在循环中使用Promise对象
- 如何在xslt中使用变量
- 在VC中如何使用VARIANT变量
- 如何在sed中使用变量
- 如何在Linux中增加默认变量
- 如何在 block 中修改外部变量
- 如何在javascript中使用django变量
- 如何在 block 中修改外部变量
- 如何在JS字符串中引用变量
- 如何在 block 中修改外部变量
- 如何在 block 中修改外部变量
- 在JSP中如何传递变量
- 【位运算知识+前缀思路+后缀思路】CS Course HDU
- 【Python】Python3多线程
- php读取文件内容
- 计算机网络传输层介绍
- 当帆软的报表设计与泛微OA的流程结合是一个经典的集成
- 如何在Promise链中共享变量?
- #Android学习# 简单的轮播图的实现[上]
- NKOJ 2439 四叶草魔杖(最小生成树+状压dp/网络流)
- 【开发也是好测试】(三)—pytest fixture scope
- keepalived+nginx高可用环境搭建
- 0904 servlet
- 已解决:mybatis 查询默认过滤值为空的字段
- 来来来,一起聊聊互联网行业的黑话,你知道哪些?
- poj1664 放苹果