我正在寻找一种通过承诺无限调用函数的方法。 我尝试了2个场景,其中一个在另一个场景中运行。 不起作用的代码的目的是:从API获取数据,然后将其存储到数据库中。
我学习了许诺,有人可以解释我为什么一个人在工作而另一个人没有工作? 在我的代码下面
工作代码 该函数只被调用一次,我希望无限地调用它
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);
代码失败
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);
答案 0 :(得分:1)
我看到你的代码丢失了2个错误。在getLtcPrice函数中,您应该在解析之前检查错误,所以。
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)
});
})
}
在saveLtcPrice函数中,您始终在解析将调用传递给异步函数。这毫无意义。你应该像在getLtcPrice函数中那样完成,所以:
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)
})
)
});
}
最后,你应该在setInterval函数中捕获错误
答案 1 :(得分:1)
在插入完成后重写saveLtcPrice以解决:
// 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);
});
答案 2 :(得分:0)
你的saveLtcPrice函数有一个非常奇怪的调用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 ");
})
)
});
}
也许你应该在最后一次回调中完成数据库操作后调用解析。
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);
}
})
});
}
看起来您尝试通过调用数据库异步操作来解决问题。由于此数据库操作接受回调作为参数,因此除undefined
之外的其他任何内容都不太可能解决您的承诺。
确保您正确处理您的承诺拒绝,并尝试使用.catch()
以便您可以捕获您的错误,否则在承诺中找到代码问题的来源可能很困难。
答案 3 :(得分:0)
再添加一个答案:
// 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();