node.js代码已知会变成回调意大利面。
在node.js中克服此问题并编写干净,不复杂,易于理解的回调代码的最佳技巧是什么?
答案 0 :(得分:8)
看看Promises:http://promises-aplus.github.io/promises-spec/
这是一个旨在解决这个问题的开放标准。
我正在使用节点模块'q',它实现了这个标准:https://github.com/kriskowal/q
简单用例:
var Q = require('q');
例如,我们有类似的方法:
var foo = function(id) {
var qdef = Q.defer();
Model.find(id).success(function(result) {
qdef.resolve(result);
});
return (qdef.promise);
}
然后我们可以通过方法链接承诺.then():
foo(<any-id>)
.then(function(result) {
// another promise
})
.then(function() {
// so on
});
也可以通过以下值创建承诺:
Q([]).then(function(val) { val.push('foo') });
还有更多,请参阅文档。
另见:
答案 1 :(得分:4)
可以采取一些措施来避免'matrioska风格'。
您可以将回调存储到变量中:
var on_read = function (foo, bar) {
// some logic
},
on_insert = function (err, data) {
someAsyncRead(data, on_read);
};
someAsyncInsert('foo', on_insert);
您可以使用一些在这些情况下有帮助的modules。
// Example using funk
var funk = require('funk');
for(var i = 0; i < 10; i++) {
asyncFunction(i, funk.add(function (data) {
this[i] = data;
}));
}
funk.parallel(function () {
console.log(this);
});
答案 2 :(得分:2)
我建议1)使用CoffeeScript和2)使用命名回调并在散列中在它们之间传递状态,而不是嵌套回调或允许参数列表变得非常长。而不是
var callback1 = function(foo) {
var callback2 = function(bar) {
var callback3 = function(baz) {
doLastThing(foo, bar, baz);
}
doSomethingElse(bar, callback3);
}
doSomething(foo, callback2);
}
someAsync(callback1);
你可以简单地写
callback1 = (state) -> doSomething state.foo, callback2
callback2 = (state) -> doSomethingElse state.bar, callback3
callback3 = (state) -> doLastThing state
someAsync callback1
您的doSomething
,doSomethingElse
和doLastThing
被重写后,使用/扩展哈希值。 (您可能需要围绕外部函数编写额外的包装器。)
正如您所看到的,此方法中的代码读取整齐且线性。并且因为所有回调都暴露出来,单元测试变得更加容易。
答案 3 :(得分:0)
尝试节点行
https://github.com/kevin0571/node-line
用法:
var line = require("line");
line(function(next) {
obj.action1(param1, function(err, rs) {
next({
err: err,
rs: rs
});
});
}, function(next, data) {
if (data.err) {
console.error(err);
return;
}
obj.action2(param2, function(err, rs) {
if (err) {
console.error(err);
return;
}
next(rs);
});
}, function(rs) {
obj.finish(rs);
});
答案 4 :(得分:0)
在大多数情况下,使用Twitter的OAuth2应用程序示例,使用Kris的Q promise库和RegisterFormset = modelformset_factory(Register, form=ModbusRegistersForm)
register_forms = RegisterFormset()
,Nodejs Express api route。首次尝试用户时间线GET。如果401响应,则刷新bearer-token然后重试用户时间线。我不得不使用https.request
来处理一个返回另一个promise(链接)或值的promise。
Q.when