Alexis Brunet
Alexis Brunet

Reputation: 355

NodeJS - infinite call on promise functions

I'm looking for a way to call infinitely a functions with promises. I tried 2 scenarios, one works the other don't. The aim of the code that doesn't works is to: get data from an API and then store it into a database.

I'm learning promises, can someone explain me why one is working and the other don't ? Below my codes

Working code The function is called only once, I'm looking to get it called infinitly

const request = require('request') //node to facilitate http request
var nano    = require('nano')('http://admin:12345@localhost:5984'); //connect to couchdb using id and password
var db_name  = nano.db.use('bitfinex'); //couchdb database name
var ltc_url = 'https://api.bitfinex.com/v1/pubticker/ltcusd' //entry point
var nonce = new Date().toISOString()  //gives a unique id
                      .replace(/T/, ' ')    // replace T with a space
                      .replace(/\..+/, '')     // delete the dot and everything after

let cleanTheRoom = function() {
      return new Promise(function(resolve, reject) {
        resolve('Cleaned the Room, ');
      });
    };

  let removedTheGarbage = function(msg) {
    return new Promise(function(resolve, reject) {
      resolve(msg + 'removed the garbage, ');
    });
  };

  let getIcecream = function(msg) {
    return new Promise(function(resolve, reject) {
      resolve(msg +'got icecream.');
    });
  };

setInterval(function(){
  cleanTheRoom()
    .then(removedTheGarbage)
    .then(getIcecream)
    .then(function(msg) {
    console.log(msg );
  });
}, 2000);

Failing code

const request = require('request') //node to facilitate http request
    var nano    = require('nano')('http://admin:12345@localhost:5984'); //connect to couchdb using id and password
    var db_name  = nano.db.use('bitfinex'); //couchdb database name
    var ltc_url = 'https://api.bitfinex.com/v1/pubticker/ltcusd' //entry point
    var nonce = new Date().toISOString()  //gives a unique id
                          .replace(/T/, ' ')    // replace T with a space
                          .replace(/\..+/, '')     // delete the dot and everything after

// get current litecoin price from Bitfinex

function getLtcPrice(){
  return new Promise(function(resolve, reject){
    request.get(ltc_url,
        function (error, response, body) {
        var rep = JSON.parse(body);
        var ltc_price = rep.ask;
          resolve (ltc_price)
        if (error){
          reject(ltc_price)
          }
      });
    })
  }

//save current litecoin price to the database

function saveLtcPrice (ltc_price){
      return new Promise(function(resolve, reject){
        resolve(
        db_name.insert({ _id: nonce, currency:"Litecoin", price: ltc_price},
           function(err, body) {
             if (!err)
             console.log(" ltc price : "+ ltc_price +", uploaded to the database ");
          })
          )
      });
    }

setInterval(function(){
  getLtcPrice()
    .then(function(ltcPrice){
      saveLtcPrice(ltcPrice);
    });
}, 2000);

Upvotes: 1

Views: 770

Answers (4)

HMR
HMR

Reputation: 39250

Adding one more answer:

// get current litecoin price from Bitfinex
const getLtcPrice = (ltc_url) =>
  new Promise(
    (resolve, reject) =>
      request.get(
        ltc_url,
        (error, response, body) =>
          error
            ? reject(error)
            : resolve(JSON.parse(body).ask)
      )
  );

//save current litecoin price to the database
const saveLtcPrice = (ltc_price) =>
  new Promise(
    (resolve, reject) =>
      db_name.insert(
        { _id: nonce, currency: "Litecoin", price: ltc_price },
        (err, body) =>
          err
            ? reject(err)
            : console.log(" ltc price : " + ltc_price + ", uploaded to the database ")
              || resolve(body)
    )
  );

const keepGettingPrice = () => {
  const rec =
    p =>
      //if previous saves were not finished then wait for it to finish
      p = p.then(
        //!!!!!!!!!!!!! where does ltc_url come from?
        _ => getLtcPrice(ltc_url)
      ).then(
        saveLtcPrice
      ).then(
        undefined,
        //handle the error
        err=>console.warn("failed one:",err,)
      )
      .then(
        x=>new Promise((r)=>setTimeout(r,2000))
      );
  return rec(Promise.resolve());
};
keepGettingPrice();

Upvotes: 0

radar155
radar155

Reputation: 2220

i see 2 errors in your falling code. In getLtcPrice function, you should check for errors before resolving, so.

function getLtcPrice(){
  return new Promise(function(resolve, reject){
    request.get(ltc_url, function (error, response, body) {
      if (error) { // check for errors immediatly
        reject(ltc_price)
        return
      }
        var rep = JSON.parse(body);
        var ltc_price = rep.ask;
        resolve(ltc_price)
      });
    })
  }

in saveLtcPrice function, you are always resolving passing a call to an async function. This make no sense. You should do exactly like you did in getLtcPrice function, so:

function saveLtcPrice (ltc_price) {
      return new Promise(function(resolve, reject) {
        db_name.insert({ _id: nonce, currency:"Litecoin", price: 
          ltc_price},function(err, document) { //changed variable name "body" to "document". it's just a convention, this is not the body of an http request, this is an object inside a database
             if (err) {
               reject(err)
               return
             }

             console.log(" ltc price : "+ ltc_price +", uploaded to the database ");
             resolve(document)
          })
          )
      });
    }

Finally, you should catch errors inside your setInterval function

Upvotes: 1

Valera
Valera

Reputation: 2913

Rewrite your saveLtcPrice to resolve after the insert was done:

// get current litecoin price from Bitfinex
function getLtcPrice(){
   return new Promise(function(resolve, reject){
       request.get(ltc_url, function (error, response, body) {
           if (error) reject(error)

           var rep = JSON.parse(body);
           var ltc_price = rep.ask;
           resolve (ltc_price)
       });
   })
}

//save current litecoin price to the database
function saveLtcPrice (ltc_price){
    return new Promise(function(resolve, reject){
        db_name.insert({
            _id: nonce,
            currency:"Litecoin",
            price: ltc_price
        }, function(error, body) {
            if(error) reject(error)

            console.log(" ltc price : "+ ltc_price +", uploaded to the database ");
            resolve(body)
      })
  });
}

Promise.resolve().then(function resolver() {
    return getLtcPrice().then(function(ltcPrice){
        return saveLtcPrice(ltcPrice);
    }).then(resolver)// both functions ended, call them again
}).catch((error) => {
    console.log("Error: " + error);
});

Upvotes: 1

John Rodney
John Rodney

Reputation: 175

Your saveLtcPrice function has a very weird placement of the call to resolve

function saveLtcPrice (ltc_price){
  return new Promise(function(resolve, reject){
    resolve( /* <--- HERE */
    db_name.insert({ _id: nonce, currency:"Litecoin", price: ltc_price},
       function(err, body) {
         if (!err)
         console.log(" ltc price : "+ ltc_price +", uploaded to the database ");
      })
      )
  });
}

Maybe you should call the resolve after the database operation has finished in the final callback.

function saveLtcPrice (ltc_price){
  return new Promise(function(resolve, reject){
    db_name.insert({ _id: nonce, currency:"Litecoin", price: ltc_price},
       function(err, body) {
         if (!err) {
           resolve(body) /* <-- Move to here */
           console.log(" ltc price : "+ ltc_price +", uploaded to the database ");
         } else {
           reject(err);
         }
       })
  });
}

What it appears is that you attempt to resolve with a call to a database async operation. Since this database operation accepts a callback as a parameter it is very unlikely your promise is resolved with anything other than undefined.

Make sure you handle your promise rejects correctly and try to use .catch() so that you can catch your errors otherwise locating the source of code problems in promises can be difficult.

Upvotes: 0

Related Questions