Search code examples
javascriptnestjses6-promise

Nest JS resolving promises from Binance API


I am trying to create an api that connects into the Binance API using node and in particular NestJs.

In my controller I have @Get('candles') endpoint and call it by going to localhost:5000/candles. I am expecting it to return an object containing all the candleData retrieved from the Binance API. I am using the npm package node-binance-api.

I know the binance.candlesticks("BTCGBP", "4h", async (error, ticks, symbol) = {... I am using is getting the data as inside I log the data received and show candleData.length in the console and it returns 100 candles as requested.

My issue is resolving the promise that this npm package returns so that I can return it via the /candles endpoint. I am used to angular and observables and I am getting a bit confused by async and await.

app.controller.ts

// Endpoint to fetch the object.
@Get('candles')
  public getCandleData() {
    console.log('Getting Candles');
 let binanceResponse = this.getBinanceCandles().then(
      (response) => {
        const result = response
        console.log('inside .then', result); // undefined
        this.candles = result
        return this.candles
      }
    );

    console.log('@Get binanceResponse', binanceResponse); // Promise { <pending> }
    return binanceResponse // undefined
}

// async function to retrieve data from Binance
async getBinanceCandles() {
    let binanceResponse = await binance.candlesticks("BTCGBP", "4h", async (error, ticks, symbol) => {
      if (error) return console.error(error);
      const candleData = await ticks.map(candle => ({
        time: candle[0],
        open: candle[1],
        high: candle[2],
        low: candle[3],
        close: candle[4]
      }))
      let last_tick = ticks[ticks.length - 1];
      let [time, open, high, low, close, volume] = last_tick;
      console.log('Length', candleData.length);
      console.info(symbol + " last close: " + close);
      return candleData
} , { limit: 100 })
 return binanceResponse
}

console output

Application is running on: http://[::1]:5000
Getting Candles
@Get binanceResponse Promise { <pending> }
inside .then undefined
Length 100
BTCGBP last close: 41628.85000000

I am not sure if I am using the await keyword correctly but clearly the promise is returning unresolved. How do I get the endpoint localhost:5000/candles to return an object containing the 100 candles created in the getBinanceCandles() function?


Solution

  • You are so close , just missing the async/await to wait for the value before return.

    @Get('candles')
    public async getCandleData() {
       ...
       return await binanceResponse
    }
    

    Other approaches is to use await/async all the way:

    @Get('candles')
    public async getCandleData() {
        try {
           console.log('Getting Candles');
           const result = await this.getBinanceCandles()
           this.candles = result  // don't know why use this.candles here, i just keep it
           return result
        } catch(e) {
           // TODO: handle error
        }
    }
    

    Wrap the binance.candlesticks in Promise to return value from callback

    async getBinanceCandles() {
        return new Promise((resolve, reject) => {
            binance.candlesticks("BTCGBP", "4h", async (error, ticks, symbol) => {
              if (error){ reject(error); }
    
              const candleData = await ticks.map(candle => ({ // is there a need to use await?
                time: candle[0],
                open: candle[1],
                high: candle[2],
                low: candle[3],
                close: candle[4]
              }))
    
              let last_tick = ticks[ticks.length - 1];
              let [time, open, high, low, close, volume] = last_tick;
              console.log('Length', candleData.length);
              console.info(symbol + " last close: " + close);
              resolve(candleData)
          } , { limit: 100 })
        })
      }