NodeJS - 对promise函数的无限调用

时间:2017-12-05 10:03:57

标签: javascript node.js api promise setinterval

我正在寻找一种通过承诺无限调用函数的方法。 我尝试了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);

4 个答案:

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