Node.js使用多个回调的正确方法

时间:2018-03-20 05:01:46

标签: node.js callback

我是Node.js的新手,很抱歉。

在我的代码中,我使用的是某些服务的API。基本上它是很多回调。这些回调提供了我需要在另一个回调中使用的服务的值。

如果是同步方式,那么我会写如下:

var value1 = 10;
var value2 = 0;
var value3 = '';
var value4 = '';

api.method1((error, data) => {
    if (error) {
        // some code
    }

    value2 = data.value1FromApi / value1;    
});

if (value2 > 0) {
    api.method2(value2, value1, (error, response) => {
        if (error) {
            // some code
        }

        value3 = response.value2FromApi;
        value4 = response.value3FromApi;
    });

    // Check status
    for (var i = 0; i < 10; i++) {
        if (value4 !== 'some status') {
            api.method3(value3, (error, response) => {
                value4 = response.value4FromApi;
            });

            // wait(1000);
        }
        else {
            break;
        }
    }

    if (value4 !== 'some status') {
        api.method4(value3, (error, response) => {

        });
    }
    else {
        // similar code as above
    }
}

我知道这是错误的代码,因为在第一次回调value2之后未完成

告诉我需要应用哪些技术或哪些技术才能解决该回调序列?

4 个答案:

答案 0 :(得分:5)

您需要以异步方式处理此问题。你可以试试这个:

api.method1((error, data) => {
    if (error) {
        // some code
    }

    value2 = data.value1FromApi / value1;
    if (value2 > 0) {
        api.method2(value2, value1, (error, response) => {
            if (error) {
                // some code
            }

            value3 = response.value2FromApi;
            value4 = response.value3FromApi;
            // Check status
            for (var i = 0; i < 10; i++) {
                if (value4 !== 'some status') {
                    api.method3(value3, (error, response) => {
                        value4 = response.value4FromApi;
                        if (value4 !== 'some status') {
                                    api.method4(value3, (error, response) => {

                                    });
                                }
                        else {
                            // similar code as above
                        }
                    });
                }
                else {
                    break;
                }
            }

        });
    }
});

基本上所有的回调都必须嵌套在彼此之中

答案 1 :(得分:1)

value2undefined,因为它是在异步函数中分配的。 value2的使用发生在函数执行之前。

您可以获得有关JavaScript EventLoop的一些知识,以便更好地理解。

PS。有许多方法可以处理异步函数和回调地狱,例如Promiseasynccoasync & await in node 8

请查看http://callbackhell.com/了解详情。

答案 2 :(得分:1)

为了链接许多请求,您需要使用promises

&#13;
&#13;
var method3CalledTimes = 0;
const api = { // Replace api with real API calls
  method1: function() { 
      return Promise.resolve({ value1FromApi: 1 }); 
  },
  method2: function() { 
      return Promise.resolve({ value2FromApi: 2, value3FromApi: 3 }); 
  },
  method3: function() { 
      if (method3CalledTimes++ <= 3) // for demo
          return Promise.resolve({ status: "not-correct-status-yet" });
      return Promise.resolve({ status: "correct-status" }); 
  },
  method4: function() { 
      return Promise.resolve("Success"); 
  }
};

var value1 = 10,
    value2, 
    value3, 
    value4;

api.method1()
  .then(function(data) {
    value2 = data.value1FromApi / value1;
    
    if (value2 <= 0) 
      return Promise.reject("v2 is non-positive");      
    
    return api.method2();    
  })
  .then(function(data) {
    value3 = data.value2FromApi;
    value4 = data.value3FromApi;
    return Promise.all([api.method3(), api.method4()]);
  })
  .then(function() {   
    return new Promise(function(resolve, reject) {
      var tryCount = 10;

      function checkStatus() 
      {
        console.log("Trying to call method3(). Attempts left: " + tryCount);
        api.method3()
          .then(function(data) {
            console.log("Status response: " + data.status);
            if (data.status === "correct-status") {
              console.log("Valid status, resolving...");
              resolve(data.status); // status did change
            } else {
              if (tryCount-- <= 0) { // if no tries left
                console.log("Invalid status, no attempts left. Failing...");
                reject("statusnotchanged"); // status didn't change after N attempts
              } else { // if we have tries
                console.log("Invalid status, we have attempts. Trying again...");
                setTimeout(checkStatus, 1000); // try again in 1 second
              }
            }
          })
          .catch(reject); // if error - reject
      }    

      checkStatus(); // call once, then it will call itself with setTimeout      
    });
  })
  .then(function(newStatus) {
    console.log("Complete! New status = " + newStatus); 
  })
  .catch(function(r) {
    if (reason === "statusnotchanged") {
      // handle this specific reason if needed
    }
    console.error(r);
  });
&#13;
&#13;
&#13;

这段代码只是一个例子,它显示了这个想法。您的代码示例意图非常不明确,因此我无法对其进行优化。

了解Promise如何使错误处理变得更容易。链中的任何拒绝都将导致执行.catch。尝试将value1设置为0以查看会发生什么。

答案 3 :(得分:1)

我在学习node.js时遇到了同样的问题。

我有一个调用外部API的文件,当用户请求路由时,我的服务器将响应作为json对象发送。

EXTERNAL API CALLS

var connection {user:“user”,密码:“password”} //这只是我的连接对象的一个​​例子

exports.getUsers = function(){
    return new Promise(function(resolve, reject){
          var params = {search_string:""};
          var users  = [];
          connection.Users.get(params, function(error, response){
               var user;
               for(let i = 0; i < response.data.length; i++)
               {
                   if(response.data[i].name=="user"
                   {
                       user = response.data[i];
                   }
               }
                   users.push({user});
               resolve(users); //return the user object
            });
        });
     };

NODE.JS SERVER

const request = require('./requests.js'); //file with my external api calls

app.get('/users', function(req, res){
     requests.getUsers()
     .then(function(users){
          res.contentType('application/json');
          res.send(JSON.stringify(users));
      })
     .catch(function(err){
          console.log(err);
     });
  });

如果您使用PROMISE,该功能将一直等到您继续之前获得所需的值。

。您可以根据需要向调用api的用户发送结果。

在MDN文档中,您可以找到关于JS的所有内容,它非常有用。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

修改

阅读更多关于promises的内容我发现了其他链接,它也很有用: http://exploringjs.com/es6/ch_promises.html