简体   繁体   English

NodeJS-对promise函数的无限调用

[英]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. 我尝试了2种情况,一种可行,另一种不可行。 The aim of the code that doesn't works is to: get data from an API and then store it into a database. 该代码无效的目的是:从API中获取数据,然后将其存储到数据库中。

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);

i see 2 errors in your falling code. 我在您的下降代码中看到2个错误。 In getLtcPrice function, you should check for errors before resolving, so. 在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)
      });
    })
  }

in saveLtcPrice function, you are always resolving passing a call to an async function. 在saveLtcPrice函数中,您始终在解决将调用传递给异步函数的问题。 This make no sense. 这没有道理。 You should do exactly like you did in getLtcPrice function, so: 您应该完全像在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)
          })
          )
      });
    }

Finally, you should catch errors inside your setInterval function 最后,您应该在setInterval函数中捕获错误

Rewrite your saveLtcPrice to resolve after the insert was done: 重写完成后,重写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);
});

Your saveLtcPrice function has a very weird placement of the call to resolve 您的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 ");
      })
      )
  });
}

Maybe you should call the resolve after the database operation has finished in the final callback. 也许您应该在最终回调中完成数据库操作后调用resolve。

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 . 由于此数据库操作接受回调作为参数,因此几乎不可能用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. 确保正确处理您的promise拒绝,并尝试使用.catch()以便您可以捕获错误,否则很难找到promise中的代码问题源。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM