首页 > 解决方案 > 如何组合来自不同 Promise 的参数?

问题描述

这个问题应该很清楚:我想使用如下语句写入日志文件。您可以假设此语句位于按钮的单击处理程序中。此伪代码中嵌入了两个问题。

pLogInfo("local info").then(pauseUntilSettled).catch(err); // This is my goal

这是我的库函数(每个都返回一个 Promise):

// Get info asynchronously from a server (simple, should work)
function pGetServerInfo()
    {
    // then value: "server info"
    } // pGetServerInfo

// Write into a file asynchronously (simple, should work)
function pWriteFile(path,string)
    {
    // no then value
    } // pWriteFile

// Write formatted info into a log file asynchronously
function pLogInfo(localInfo)
    {
    pGetServerInfo().then(p2);
    } // pLogInfo

function p2(serverInfo)
    {
    // Should write "local info, server info"
    // But where is the local info? It got lost.
    return pWriteFile('log',localInfo+','+serverInfo);
    } // p2

用法:

pLogInfo("local info").then(pauseUntilSettled).catch(err);

function pauseUntilSettled()
    {
    // How to wait before returning from
    // the button click event handler?
    } // pauseUntilSettled

2019 年 8 月 27 日添加:

我想到了这个常见问题的几种可能的解决方案:

  1. 将对象附加到链中的顶级函数之一 (p.data={})。您可以在对象中存储您希望的任何参数或回调,并在任何异步“then”代码中引用它们。这是有效的,因为作为对象父级的函数具有全局范围。如果在现有 Promise 尚未解决的情况下触发同一线程的另一个顶级 Promise,它可能会失败,因为新的执行线程将共享并覆盖该对象。我已经成功地使用了这种方法,是上述全局公式的一种变体,但它显然是不安全的。

  2. 创建一个闭包函数来传播异步线程。闭包函数包含其参数和引用的全局变量的快照。我还没有把这个想法付诸实践,但这似乎是合理的。

  3. 创建一个新的 Promise,作为 Promise 线程的一部分或作为单独的助手,它使用对象而不是单个值调用其解析函数。使用该对象将多个值传播到每个“then”函数。我也没有得到这个想法。

我希望这些想法能激发某人(包括我自己)提出解决方案,因为这是一个非常常见的问题,很少被讨论。

标签: javascriptpromise

解决方案


Satpal 对承诺给出了很好的回答。另一种选择是使用 RXJS 库并利用构建在 Promises 之上的 observables。它们有一个 next()、error() 和 complete() 块,其中代码只有在流中接收到值后才会执行。如果您想等待多个服务响应,您可以通过多种方式将流组合在一起。

我知道这不是您正在寻找的确切答案,但它是一个非常有用的库。这是文档。https://rxjs-dev.firebaseapp.com/api/index/class/Observable


推荐阅读