Javascript NodeJS-承诺函数的无限调用
我正在寻找一种方法,可以无限调用有承诺的函数。 我尝试了两种方案,一种有效,另一种无效。 不起作用的代码的目的是:从API获取数据,然后将其存储到数据库中 我在学习承诺,有人能解释一下为什么一个在工作而另一个不工作吗? 在我的代码下面 工作代码 函数只被调用一次,我希望它被无限次调用Javascript NodeJS-承诺函数的无限调用,javascript,node.js,api,promise,setinterval,Javascript,Node.js,Api,Promise,Setinterval,我正在寻找一种方法,可以无限调用有承诺的函数。 我尝试了两种方案,一种有效,另一种无效。 不起作用的代码的目的是:从API获取数据,然后将其存储到数据库中 我在学习承诺,有人能解释一下为什么一个在工作而另一个不工作吗? 在我的代码下面 工作代码 函数只被调用一次,我希望它被无限次调用 const request = require('request') //node to facilitate http request var nano = require('nano')('http://
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);
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 ");
})
)
});
}
功能保存LTCPRICE(ltc\U价格){
返回新承诺(功能(解决、拒绝){
解析(/*我在下降的代码中看到了两个错误。在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函数中的错误,重写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);
});
补充一个答案:
// 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();
您收到了哪些错误消息。您能提供更多信息吗?如果setInterval的处理程序再次触发时,上一个调用尚未完成怎么办?它是否应该等待上一个请求要结束吗?@ZombieChowder:我实际上没有收到任何错误消息,只是它只在您仍然有getLtcPrice
错误时才运行:您需要else
以便只调用一个分支:如果有错误,可能没有要解析的主体。@Duncan不正确。如果您拒绝在承诺内执行代码,代码将立即执行这不是任何文档所说的,也不是内置Promise实现所做的。请在浏览器控制台中尝试:new Promise(函数(解析,拒绝){reject('rejected');console.log('foo');})
它将输出foo
以及拒绝承诺。拒绝不会停止,但一旦被拒绝;调用resolve不会做任何事情。抛出错误只会返回被拒绝的承诺,因此没有问题(也不会多次拒绝)。请注意,当您使用Promise polyfil时,任何事情都可能发生,因此最好在调用resolve或rejectreject(err);return之后返回;
@Duncan这是毫无疑问的,是:-)我个人赞成if(err)reject(err)else resolve(res)
我相信不使用setTimeout或setImmediate的递归函数会导致堆栈溢出
。如果它包含在一个承诺中,我可能是错的。我现在很好奇。@JohnRodney:这不会导致堆栈溢出。。然后(解析器)
计划以后运行解析器
,不再需要当前的解析器的堆栈框架。另请参见requestAnimationFrame
@Ryan的典型用法。此注释放在这个答案的旧版本上,我在解析承诺后执行了一个递归函数,该函数调用了自身ch确实导致了stackoverflow@Valera:我不认为它能很好地工作!:)谢谢大家的帮助。我仍然需要实践这些承诺,以充分理解如何正确设置它。请使用适当的if
语句,并使用块来消除副作用?console.log(…)&&
甚至不起作用。@Bergi是的,忘记了console.log返回未定义的。通常只需像这样将它们压缩以进行调试,这样我就不需要为函数添加{}
。
// 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();