Reputation: 355
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
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
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
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
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