Node.js连续方法调用嵌套回调格式

时间:2016-05-19 00:24:12

标签: node.js

所以我是Node.js的新手,我只是想知道我的代码设置方式是否合理。我来自Java背景,因此嵌套的回调结构是新的。我有一个Node程序运行一堆代码,我分解成不同的方法。问题是需要按顺序调用方法。我的代码现在有这个结构:

functionOne(data, callback(err) {

   functionTwo(data, callback(err) {

      functionThree(data, callback(err) {

          functionFour(data, callback(err) {
             //Code
          });

      });

   });

});

这是非常简约的,但这个结构还可以吗?使用Java,我将获取所有方法的返回值,然后将它们传递给下一个函数。根据我的理解,到目前为止,我刚刚提到的Java方法是Node.js试图消除的主要内容之一。但无论如何......那个结构看起来还不错,那是它的意图吗?只是想确保我一般不会对Node造成任何重大错误。谢谢!

3 个答案:

答案 0 :(得分:5)

如果使用回调模式,您的代码结构看起来很好。 但是,如果您对使代码更清晰可读感兴趣,那么您希望在异步函数中使用Promises,因此您可以执行以下操作,而不是将回调传递给函数:

function asyncFunction (data){
   return new Promise(function(resolve, reject){
       // Do something with data
       // Here you can call reject(error) to throw an error
       resolve();
   });
}

而不是嵌套函数回调,你可以调用Promise的方法。

asyncFunction(data)
.then(function(){
    // Promise resolved
    // Something has been done with data
});

使用Promise,您还可以并行执行异步功能:

Promise.all([asyncFunctionA(data), asyncFunctionB(data), asyncFunctionC(data)])
.then(function(){...});

修改

如果需要将一个函数的值传递给另一个函数,则代码应如下所示:

asyncFunctionA(data)
.then(function(dataA){
    return asyncFunctionB(dataA);
})
.then(function(dataB){
    return asyncFunctionC(dataB);
})
.then(function(dataC){
// ...
});

答案 1 :(得分:3)

你应该尝试使用promises来避免你的回调地狱,所以它可能是这样的......

const Q = require('q'); // you can do a research for this module.
var myModule = {};
myModule.functionOne = (params) => {
  const deferred = Q.defer(); // wait for this to complete
  // body function
  deferred.resolve(data); // this would be the result of this function
  return deferred.promise; // data is the output on your function
}

myModule.functionTwo = (params) => {
  const deferred = Q.defer(); // wait for this to complete
  // body function
  deferred.resolve(data); // this would be the result of this function
  return deferred.promise; // data is the output on your function
}

myModule.doAll = (params) => {
   myModule.functionOne(params)
   .then((outputFunctionOne) => {
      // this is called after functionOne ends
      return myModule.functionTwo(outputFunctionOne);
   })
   .then((outputFunctionTwo) => {
      // this is called after function 2 ends
      if (outputFunctionTwo.success) {
        // if everything ok, resolve the promise with the final output
        deferred.resolve(outputFunctionTwo);
      } else {
        // reject the promise with an error message
        deferred.reject('error');
      }
   })
   .fail((err) => { 
      // this is call if the promise is rejected or an exception is thrown
      console.log(err); // TODO: Error handling
   })
   .done();
}

module.exports = myModule;

你可以轻松地链接尽可能多的承诺,这样你就可以摆脱回调地狱。最好的部分,您可以在Javascript或Node.js上做承诺

参考链接https://github.com/kriskowal/q

希望这有帮助

答案 2 :(得分:2)

其他大多数答案都以Promise / A作为回调问题的答案。这是正确的,对你有用。但是,如果您愿意放弃使用javascript作为工作语言,我想再给您一个选择。

介绍冰咖啡,这是CoffeeScript项目的一个分支。

用冰咖啡你会写:

await functionOne data, defer err
await functionTwo data, defer err2
await functionThree data, defer err3
//etc

然后编译成CoffeeScript:

functionOne data, (err) ->
   functionTwo data, (err2) ->
      functionThree data, (err3) ->
         //etc

然后编译为您的Javascript。

functionOne(data, callback(err) {

   functionTwo(data, callback(err2) {

      functionThree(data, callback(err3) {
          //etc    
      });    
   });    
});