-1

I'm quite new to Node.js. I would like to call an API and wait the result before to do something.

// endpoint
function getListMarket() {
  var deferred = Q.defer();
  deferred.resolve(Q().then(getMarkets)
  .then(calculIndicators));
  return deferred.promise;
}

// Get a list
function getMarkets() {
  var deferred = Q.defer();
  bittrex.getmarketsummaries(function (data, err) {
    if (err) deferred.reject(err.name + ': ' + err.message);
    if (data) {
      var listMarkets = [];
      for (var i in data.result) {
         listMarkets.push(data.result[i]);
      }

      deferred.resolve(listMarkets);
    }
  });

  return deferred.promise;
}

// Update a Coin
function calculIndicators(coinList) {
  var deferred = Q.defer();
  var promises = [];
  coinList.forEach(function (coin) {
    promises.push(getCandles(coin).then(getIndicators(coin)));
  });

  Q.allSettled(promises).then(function (results) {
    console.log('3 ---------------------------------------------');
    var listMarkets = [];
    results.forEach(function (r) {
       console.log("result ok" + r.value.name);
    });

    deferred.resolve(listMarkets);
  });

  return deferred.promise;
}

// Get a information needed to update the coin
function getCandles(coin) {
  var deferred = Q.defer();
  bittrex.getcandles({
    marketName: coin.MarketName,
    tickInterval: 'hour', // intervals are keywords (oneMin, fiveMin, hour, thirtyMin, Day)
  }, function (data, err) {
        if (err) {
          deferred.reject(err.name + ': ' + err.message);
        }

        if (data) {
          console.log('1 : data');
          coin.Test= 10;
          deferred.resolve(coin);
        }
      });

  return deferred.promise;
}

// Update the coin with the information from getCandles
function getIndicators(coin) {
  console.log('2 : ' + coin.Test);
}

In this case, when I call my function getListMarket, the output is :

2 : undefined
2 : undefined
2 : undefined
...
1 : data
1 : data
1 : data
...
3 ---------------------------------------------

Can you explain me why the log "2" is called before the 1 in this case ? I think the api in getCandles is an Asynchronous Calls but I don't know why. I need the result of this api in the function getIndicators.

Andrew Lohr
  • 5,380
  • 1
  • 26
  • 38
holegeek
  • 97
  • 2
  • 12

1 Answers1

0

It's not clear everything you're trying to do here, but you need to do a whole bunch of things better:

  1. Avoid the deferred anti-pattern (wrapping a promise in another manually created promise).
  2. Make sure you're always returning the resolved value from within a .then() handler.
  3. Avoid calling your function too early when passing to .then(). It should be .then(fn), not .then(fn()).
  4. Fill in some missing code that sets the value of listMarkets.

Here's the code with a bunch of things fixed (the code still seems unfinised in several areas as it's not clear what you're trying to do in some places):

// endpoint
function getListMarket() {
  return getMarkets().then(calculIndicators);
}

// Get a list
function getMarkets() {
  var deferred = Q.defer();
  bittrex.getmarketsummaries(function (data, err) {
    if (err) {
        deferred.reject(err.name + ': ' + err.message);
    } else {
      var listMarkets = [];
      for (var i in data.result) {
         listMarkets.push(data.result[i]);
      }
      deferred.resolve(listMarkets);
    }
  });
  return deferred.promise;
}

// Update a Coin
function calculIndicators(coinList) {
  var promises = [];
  coinList.forEach(function (coin) {
    promises.push(getCandles(coin).then(getIndicators));
  });

  return Q.allSettled(promises).then(function (results) {
    console.log('3 ---------------------------------------------');
    var listMarkets = [];
    results.forEach(function (r) {
       console.log("result ok" + r.value.name);
    });

    // Fixme: you need ro fill in listMarkets here
    return listMarkets;
  });
}

// Get a information needed to update the coin
function getCandles(coin) {
  var deferred = Q.defer();
  bittrex.getcandles({
    marketName: coin.MarketName,
    tickInterval: 'hour', // intervals are keywords (oneMin, fiveMin, hour, thirtyMin, Day)
  }, function (data, err) {
        if (err) {
          deferred.reject(err.name + ': ' + err.message);
        } else {
          console.log('1 : data');
          coin.Test= 10;
          deferred.resolve(coin);
        }
      });

  return deferred.promise;
}

// Update the coin with the information from getCandles
function getIndicators(coin) {
  console.log('2 : ' + coin.Test);
  return coin;
}
jfriend00
  • 683,504
  • 96
  • 985
  • 979