代码之家  ›  专栏  ›  技术社区  ›  Alexis Brunet

NodeJS-无限调用承诺函数

  •  1
  • Alexis Brunet  · 技术社区  · 6 年前

    我在寻找一种方法,用承诺无限调用函数。 我试过两个场景,一个可行,另一个不行。 代码不起作用的目的是:从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 回复  |  直到 6 年前
        1
  •  1
  •   Valera    6 年前

    在插入完成后,重写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
  •  1
  •   radar155    6 年前

    我看到你的下降代码中有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函数中的错误

        3
  •  0
  •   John Rodney    6 年前

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

    也许您应该在最终回调中完成数据库操作后调用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);
             }
           })
      });
    }
    

    看起来,您试图通过调用数据库异步操作来解决问题。由于此数据库操作接受回调作为参数,因此您的承诺不太可能用除以下内容之外的任何内容来解决 undefined .

    确保正确处理拒绝承诺的情况,并尝试使用 .catch() 因此,您可以捕捉错误,否则在promises中查找代码问题的源代码可能会很困难。

        4
  •  0
  •   HMR    6 年前

    再添加一个答案:

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