【问题标题】:Trying to run async and sync in series, inside foreach, gives empty result尝试在 foreach 内连续运行异步和同步,结果为空
【发布时间】:2016-02-26 18:16:15
【问题描述】:

所以,我正在尝试在forEach 中串联运行异步函数和同步操作:

       Exchange.all().then(function (result) {
            if (!result) {
                return res.json({success: false, error: 'No exchanges records were found.'});
            }
            var exchanges = [];

            result.forEach(function (exchange) {
                var getCurrencyPairs = function (pairsResult) {
                    CurrencyPair.findAll({where: {exchangeId: exchange.id}}).then(function (pairs) {
                        var currencyPairs = [];

                        pairs.forEach(function (pair) {
                            var data = pair.dataValues;
                            currencyPairs.push({
                                baseCurrency: data.baseCurrency,
                                quoteCurrency: data.quoteCurrency,
                                marginPercentage: data.marginPercentage
                            });
                        });

                        return pairsResult(null, currencyPairs);
                    });
                };

                async.waterfall([
                    getCurrencyPairs
                ], function (err, currencyPairs) {
                    exchanges.push({
                        id: exchange.stringId,
                        name: exchange.name,
                        currencyPairs: currencyPairs,
                        depositAddress: 'sample address for now'
                    });
                    // here I have `exchanges` filled correctly after each loop iteration
                });
            });
            // here `exchanges` is completely empty
            return res.json({success: true, data: exchanges});
        });

一切正常,除了forEach 循环完成后exchanges 数组为空。 AFIK,forEach 是同步的,所以我不必从它返回任何回调,并且在forEach 完成之前,该过程不会到达return res.json(),对吧?另外,在循环内部,我将值分配给在循环外部声明的全局变量。我不明白为什么这个过程会这样 - 全局数组 exchanges 在循环内被正确填充,但在循环外已经是空的。

我想也许我必须将整个 result.forEach 封装在另一个函数中,并将其结果作为回调返回,但是:

  1. 我不明白这是正确解决方案背后的逻辑
  2. 我无法想象如何实现它

【问题讨论】:

    标签: node.js asynchronous callback


    【解决方案1】:

    首先,您不必重新定义 getCurrencyPairs 函数,而且不需要async.waterfall。然后,尝试一个递归函数,例如:

    // Define getCurrencyPairs only once
    var getCurrencyPairs = function (exchange, callback) {
       CurrencyPair.findAll({where: {exchangeId: exchange.id}}).then(function (pairs) {
           var currencyPairs = [];
    
           pairs.forEach(function (pair) {
              var data = pair.dataValues;
              currencyPairs.push({
                  baseCurrency: data.baseCurrency,
                  quoteCurrency: data.quoteCurrency,
                  marginPercentage: data.marginPercentage
              });
           });
    
           callback(currencyPairs);
        });
    };
    
    // Start the program-logic
    Exchange.all().then(function (result) {
        if (!result)
            return res.json({success: false, error: 'No exchanges records were found.'});
    
        var exchanges = [];
        var createExchangesObject = function(exchange){
            if(!exchange) // If there is no exchange, we obviously "poped" everything out of result and we are done
                return res.json({success: true, data: exchanges});
    
            getCurrencyPairs(exchange, function (currencyPairs) {
                exchanges.push({
                    id: exchange.stringId,
                    name: exchange.name,
                    currencyPairs: currencyPairs,
                    depositAddress: 'sample address for now'
                });
    
                // Call your selfe (recursively), with the next result
                createExchangesObject(result.pop());
             });
        }
    
        createExchangesObject(result.pop());
    });
    

    【讨论】:

    • 但我需要以某种方式将exchange.id 传递给getCurrencyPairs 函数...我添加了exchange 参数,例如`var getCurrencyPairs = function (exchange, callback) {...}`然后在 create ExchangesObject function I call getCurrencyPairs(function (exchange, currencyPairs) {...}` 内,但它不是那样工作的。
    • 查看最新更新,我向 getCurrencyPairs 添加了与您建议的类似的交换,但写了getCurrencyPairs(exchange, function (currencyPairs) 而不是getCurrencyPairs(function (exchange, currencyPairs) 。这就是它应该如何工作
    • 只是一个小问题,因为我还没有得到承诺 - 这个解决方案不使用任何承诺,对吗?这只是一个简单的递归回调流程?因为我收到警告:Warning: a promise was created in a handler but was not returned from it 我想要一个干净的堆栈。
    • 啊,我明白了...承诺警告在CurrencyPair.findAll(...).then(function (pairs) {...}),但我不知道为什么。
    猜你喜欢
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-08
    • 1970-01-01
    • 1970-01-01
    • 2020-07-26
    • 2017-02-10
    相关资源
    最近更新 更多