所以我是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造成任何重大错误。谢谢!
答案 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
});
});
});