如何在函数返回对象数组时使用promises

时间:2016-01-06 09:47:47

标签: javascript node.js promise bluebird

我有一个不使用Promises的复杂Node应用程序,但我已经意识到我有一个需要解决的异步问题,而Promise似乎是一种可能的方法。不过,我对Promise没有经验,而且我发现学习曲线具有挑战性。

为了保持封装和可测试性,应用程序的一个部分与另一个部分之间的主要接口是要执行的操作的列表。这只是一个对象数组,其中包含调用函数用于执行操作的属性。因此,第一个模块更抽象,只需指定要采取的通用操作,而调用模块是一个针对特定后端API执行操作的具体实现。为了保持封装和可测试性,通用模块需要保持不知道特定模块。

我遇到的问题是,现在需要由通用模块确定一系列异步步骤,其中后续步骤在特定模块中执行的早期操作完成之前不会发生。但是,由于通用模块无法了解特定模块,因此无法自行执行操作。它所能做的只是将动作返回到特定模块。

但是特定模块需要执行操作,然后执行通用模块已确定的其他操作。

这是我被困的地方。我不知道如何将动作对象列表及其可执行的动作从通用模块返回到特定模块。我不知道这是因为我对Bluebird缺乏了解,还是我想尝试做一些Bluebird无法做到的事情。

似乎有一种方法是将afterExecution属性添加到操作中,这将是操作完成后要调用的后续函数。然而,这感觉很像本土的Promises,所以我不愿意走那条路。

如果你仍然能够遵循这个令人困惑的场景,那么我要问的是如何返回一个同样具有"回调的行动列表"处理主要操作对象后要执行的函数。这是Bluebird可以处理的事情吗?

修改: 经过一段时间的睡眠,我希望能够说明我的目标。这是我目前实施的精简版。

generic.js (无法了解 specific.js ):

function createActions() {
    var actions = []

    var action1 = {command:'buy', qty:100, symbol:'S', price:3.50}
    var self = this
    action1.afterwards = function() {
       self.setStopAndTarget()
    }
    actions.push(action1)
    // add some more actions

    return actions
}

specific.js

Promise.method(function checkForTrades() {
    var actions = generic.createActions()
    actions.forEach(function(a) {
        if( a.command === 'buy' ) {
            buyStock(a.symbol, a.qty, q.price).then(function(a) {
                if( a.afterwards ) {
                    a.afterwards()
                }
            })
        }
    })
})

因此, specific.js generic.js 中调用createActions()以获取操作列表。 actions是一个JSON对象数组,但正如您所看到的,我还在action中添加了一个名为afterwards的属性。

specific.js 然后处理actions。在action完成后,我使用Promise检查是否存在属性afterwards。如果它存在,我调用它。

我真正想做的是将then()编码在 generic.js 中,而不是 specific.js ,这样我就不会# 39; t必须创建afterwards属性作为action的一部分。但我无法弄清楚如何做到这一点。

我的工作原理,但我非常确定Promise可以执行此操作而无需将afterwards添加到action

此外,如果一系列操作回来,我想知道在所有操作完成之前如何推迟then()操作。我非常确定这只是使用Promises.all的问题,但查看语法会很有帮助。

谢谢!

2 个答案:

答案 0 :(得分:0)

我不确定我理解你的问题,但这里有一些想法。

如果您在进行下一步之前告诉我需要同步一组响应,则可以使用Promise.allPromise.join来执行此操作。

它们之间的区别就在于你传递参数的方式。 Promise.all获取了一个数组,而Promise.join获取了一个可用参数列表。

两者的工作方式相同:只有当所有输入承诺解决时,结果承诺才会解决。如果其中任何一个被拒绝,那么所产生的承诺也将被拒绝。

因此,如果您有一组异步进程,那么您所要做的就是为每个进程创建一个承诺,然后将这些承诺传递给Promise.all

答案 1 :(得分:0)

根据您要完成的细节,有几种模式可能与此相关。

也许最有希望的是使用promises实现的一种常规方法(在使用promises时,请将“回调”这个词放在你的脑海中)。

在这种方法中,通用模块将调用特定模块中的函数,该函数返回完成时的承诺。然后,通用模块将其以下执行步骤从特定模块返回的承诺中挂起。这是一个非常基本的实现:

function generic() {
  var specifics = [specific1, specific2, specific3];
  var promise = Promise.resolve();
  for (var i = 0; i < specifics.length; i++) {
    promise = promise.then(specifics[i]);
  }
  return promise;
}

function specific1() {
  return specific1_async_thing() . then(specific2_async_thing);
}

换句话说,specific1“回调”通用方面的方式是返回对它的承诺,为通用方提供知道(通过then)何时执行其的方法下一步。

上述逻辑将按顺序执行通用步骤 - 还有其他方法适用于其他方案,例如将所有特定人员一起开始。

考虑异步函数可能也很有用。他们允许将generic函数重写为

async function generic() {
  var specifics = [specific1, specific2, specific3];
  for (var i = 0; i < specifics.length; i++) {
    await specifics[i];
  }
}