简体   繁体   中英

Promise after forEach loop

I am new to promises and trying to figure out for quite a long time now how to get proper results after the usage of a async network call with which I receive data.

I receive my balance from a exchange and loop through several parameters. When this is finished the holdings should be returned.

However, I still have to fight the async behaviour. When I run the code without the commented code, the result is [] . If I set a artificial setTimeout, then the returned array holdings is visible properly.

Can someone tell me please where my mistake lays? I tried to read through docs of mdn and similar problems here on stackoverflow but I am nonetheless stuck.

Thank you guys very much,

Tobias

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);
  })

You're resolving your promise instantaneously but the data is not here yet, as it is happened asynchronously during the callback. Your promise should be resolved after every callback.

What you should do is create a promise for each of the request and then resolve your function with a 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));
  });
});

Your getBalance promise will be resolved when all of your promise are resolved. Be cautious though, if one of your promise is rejected, then the whole promise will be rejected.

If it's properly resolved, then the value will be an array of each value of the promises.

Since I'm assuming bittrex.getticker is async, you should instead just wrap each call into a promise and not try to combine them into one manually.

Here's a loose concept.

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM