如何组合来自单独承诺的参数



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

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

添加 8/27/19:

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

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

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

  3. 创建一个新的 Promise,作为
  4. Promise 线程的一部分或作为单独的帮助程序,该函数使用对象而不是单个值调用其 resolve 函数。使用该对象将多个值传播到每个"then"函数。我也没有让这个想法奏效。

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

Satpal给出了一个很好的答案。另一种选择是使用 RXJS 库并利用建立在 Promise 之上的可观察量。它们有一个 next()、error() 和 complete() 块,其中代码仅在流中收到值后执行。如果要等待多个服务响应,可以通过多种方式将流组合在一起。

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

解决方案:

您可以使用"bind"显式地将中间值放在任何稍后的"then"函数的作用域中。这是一个很好的解决方案,不需要更改 Promise 的工作方式,只需要一两行代码来传播值,就像错误已经传播一样。

下面是一个完整的示例:

// Get info asynchronously from a server
function pGetServerInfo()
{
// then value: "server info"
} // pGetServerInfo
// Write into a file asynchronously
function pWriteFile(path,string)
{
// no then value
} // pWriteFile
// The heart of the solution: Write formatted info into a log file asynchronously,
// using the pGetServerInfo and pWriteFile operations
function pLogInfo(localInfo)
{
var scope={localInfo:localInfo}; // Create an explicit scope object
var thenFunc=p2.bind(scope); // Create a temporary function with this scope
return (pGetServerInfo().then(thenFunc)); // Do the next 'then' in the chain
} // pLogInfo
// Scope of this 'then' function is {localInfo:localInfo}
function p2(serverInfo)
{
// Do the final 'then' in the chain: Writes "local info, server info"
return pWriteFile('log',this.localInfo+','+serverInfo);
} // p2

可以按如下方式调用此解决方案:

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

(注意:已测试此解决方案的更复杂和完整的版本,但不是此示例版本,因此可能存在所编写的错误。

最新更新