【问题标题】:Promise after forEach loopforEach 循环后的承诺
【发布时间】:2018-01-05 15:16:12
【问题描述】:

我是 Promise 的新手,并且在很长一段时间内都在试图弄清楚如何在使用接收数据的异步网络调用后获得正确的结果。

我从交易所收到余额并循环访问多个参数。完成后,应返回 holdings

但是,我仍然必须与异步行为作斗争。当我运行没有注释代码的代码时,结果是[]。如果我设置了一个人为的 setTimeout,那么返回的数组holdings 是正确可见的。

谁能告诉我我的错误在哪里?我试图在 stackoverflow 上阅读 mdn 文档和类似问题,但我仍然卡住了。

非常感谢你们,

托比亚斯

const bittrex = require('node.bittrex.api');
const {key, secret} = require('./key')

let getBalance = new Promise((resolve, reject) => {
  let holdings = [];
  bittrex.getbalances( function( data, err ) {
    if (err) {
      reject(err);
    }
    data.result.forEach(coin => {
      if (coin.Balance !== 0) {
        let market = `BTC-${coin.Currency}`;
        if(coin.Currency === 'BTC') market = `USDT-BTC`;
        bittrex.getticker( { market : market}, function( ticker, err ) {
          if (err) {
            reject(err);
          }
          holdings.push({
            Coin: coin.Currency,
            Balance: coin.Balance,
            Last: ticker.result.Last
          });
        })
      }
    });
  });
  resolve(holdings);
})

getBalance
// .then((holdings) =>{
//   return new Promise((resolve, reject)  => {
//     setTimeout(() => {
//       resolve(holdings);
//     }, 10000)
//   })
// })
  .then((holdings) => {
        console.log(holdings);
  })

【问题讨论】:

  • getticker() 也是异步的

标签: javascript asynchronous foreach es6-promise


【解决方案1】:

您正在立即解决您的承诺,但数据尚未出现,因为它是在回调期间异步发生的。你的承诺应该在每次回调后得到解决。

您应该为每个请求创建一个承诺,然后使用 Promise.all 解决您的函数

const bittrex = require('node.bittrex.api');
const {key, secret} = require('./key')
let getBalance = new Promise((resolve, reject) => {
  let holdings = [];
  bittrex.getbalances( function( data, err ) {
    if (err) {
      reject(err);
    }
    const promises = data.result.map(coin => new Promise((resolve, reject) => {
      if (coin.Balance !== 0) {
        let market = `BTC-${coin.Currency}`;
        if(coin.Currency === 'BTC') market = `USDT-BTC`;
        bittrex.getticker( { market : market}, function( ticker, err ) {
          if (err) {
            reject(err);
          }
          resolve({
            Coin: coin.Currency,
            Balance: coin.Balance,
            Last: ticker.result.Last
          });
        })
      }
    });

    resolve(Promise.all(promises));
  });
});

当您的所有承诺都解决后,您的 getBalance 承诺将被解决。不过要小心,如果你的一个承诺被拒绝,那么整个承诺都会被拒绝。

如果正确解析,则该值将是每个 promise 值的数组。

【讨论】:

  • 感谢您的回答,让我对 Promise 有了更好的理解。 TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined 尽管我尝试实现您的版本,但我认为我仍然有遗漏 return 语句的问题。知道在哪里吗?
  • 知道了。我还没有看到 .map 函数,而是用 forEach 尝试过......非常感谢你 2 回答我。掌握这个想法感觉很好 :-) 干杯
  • 感谢@Axnyff 的解释。这对我帮助很大。
【解决方案2】:

由于我假设 bittrex.getticker 是异步的,因此您应该将每个调用包装成一个 Promise,而不是尝试手动将它们组合成一个。

这是一个松散的概念。

function getTicker(...) {
    return new Promise(function(resolve, reject) {
        bittrex.getticker(..., function(ticker, error) {
            if (error) { reject(error); }
            else { resolve(ticker); }
        });
    });
}

var lotsOfPromises = data.result.map(function(coin) {
    return getTicker(...).then(function(ticker) {
        return { yourOutputdata }
    });
});

Promise.all(lotsOfPromises);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-13
    • 1970-01-01
    • 2016-02-19
    • 1970-01-01
    • 2014-11-25
    • 2023-03-20
    相关资源
    最近更新 更多