Javascript NodeJS-承诺函数的无限调用

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://

我正在寻找一种方法,可以无限调用有承诺的函数。 我尝试了两种方案,一种有效,另一种无效。 不起作用的代码的目的是:从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);

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或reject
reject(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();