Javascript 回调地狱和嵌套承诺之间的区别
我最近开始使用NodeJS和MongoDB(使用Monk)。这就是我遇到“地狱”这个词的时候。在我的代码中,我也在做同样的事情。例如-Javascript 回调地狱和嵌套承诺之间的区别,javascript,node.js,callback,Javascript,Node.js,Callback,我最近开始使用NodeJS和MongoDB(使用Monk)。这就是我遇到“地狱”这个词的时候。在我的代码中,我也在做同样的事情。例如- DBCall(d1, function(e, docs){ if(docs.length!=0) DBCall(d2, function(e, docs1){ if(docs1.length!=0) DBCall(d3, function(e, docs2){ //doing something with docs,docs1,d
DBCall(d1, function(e, docs){
if(docs.length!=0)
DBCall(d2, function(e, docs1){
if(docs1.length!=0)
DBCall(d3, function(e, docs2){
//doing something with docs,docs1,docs2
})
})
})
这是我开始阅读“承诺”的时候,我看到了这篇文章-
因为我在第三次回调中同时需要docs和docs1,所以我使用了嵌套承诺
DBCall(d1)
.then(function(docs){
if(docs.length!=0)
return DBCall(d2)
.then(function(docs1){
if(docs1.length!=0)
return DBCall(d3)
.then(function(docs2){
//doing something with docs,docs1,docs2
})
})
})
从上面的代码片段中,我有以下问题(/疑问):
我对承诺这个概念还不熟悉。感谢您的帮助 基本上,承诺的目的是允许功能组合和错误处理,以一种同步读取的方式。承诺允许您以线性(可能是错误的术语)或同步方式读取代码 这是一个比较宽泛的问题,但请查看这些建议的链接
编辑: 在阅读了你的更新之后,你本质上要求的是加入承诺(我想) 这提供了一些很好的信息。一些更好的库具有实用功能来帮助实现这一点
例如,如果使用bluebird查看一下基本上,Promises的目的是以同步读取的方式允许功能组合和错误处理。承诺允许您以线性(可能是错误的术语)或同步方式读取代码 这是一个比较宽泛的问题,但请查看这些建议的链接
编辑: 在阅读了你的更新之后,你本质上要求的是加入承诺(我想) 这提供了一些很好的信息。一些更好的库具有实用功能来帮助实现这一点 例如,如果使用蓝鸟,请查看 除了使代码更具可读性外,承诺是否具有性能优势 可能不会 嵌套承诺和回调地狱看起来很像我。实际上有什么区别吗 承诺不会自动阻止地狱。但因为它们比“简单”回调更灵活,所以它们可以用不同的方式组合,这使得避免回调地狱更容易
因为我在第三次回调中同时需要docs和docs1,所以我使用了嵌套承诺
DBCall(d1)
.then(function(docs){
if(docs.length!=0)
return DBCall(d2)
.then(function(docs1){
if(docs1.length!=0)
return DBCall(d3)
.then(function(docs2){
//doing something with docs,docs1,docs2
})
})
})
有时,嵌套的承诺是不可避免的。但是,如果它们不必按顺序执行,则不需要嵌套它们。您可以并行执行它们:
Promise.all([
DBCall(d1),
DBCall(d2),
DBCall(d3)
]).then(function(docs) {
// docs is an array: [docs, docs1, docs2]
});
除了使代码更具可读性外,承诺是否具有性能优势
可能不会
嵌套承诺和回调地狱看起来很像我。实际上有什么区别吗
承诺不会自动阻止地狱。但因为它们比“简单”回调更灵活,所以它们可以用不同的方式组合,这使得避免回调地狱更容易
因为我在第三次回调中同时需要docs和docs1,所以我使用了嵌套承诺
DBCall(d1)
.then(function(docs){
if(docs.length!=0)
return DBCall(d2)
.then(function(docs1){
if(docs1.length!=0)
return DBCall(d3)
.then(function(docs2){
//doing something with docs,docs1,docs2
})
})
})
有时,嵌套的承诺是不可避免的。但是,如果它们不必按顺序执行,则不需要嵌套它们。您可以并行执行它们:
Promise.all([
DBCall(d1),
DBCall(d2),
DBCall(d3)
]).then(function(docs) {
// docs is an array: [docs, docs1, docs2]
});
从技术上讲,您的嵌套承诺仍在使用回调,因此再次创建“回调地狱”。这一次有更多的代码。如果我使用承诺,如果我想使用docs,docs1,docs2,那么没有办法避免回调地狱吗?@User-看看我更新的答案中的一些链接。从技术上讲,你的嵌套承诺仍然在使用回调,从而再次创建“回调地狱”。这一次有更多的代码。如果我使用承诺,如果我想使用docs,docs1,docs2,那么没有办法避免回调地狱吗?@User-看看我更新答案中的一些链接。这是一个很好的解决方案。但我的情况稍微复杂一点。为了更好的理解,我编辑了这个问题。这是一个很好的解决方案。但我的情况稍微复杂一点。为了更好的理解,我编辑了这个问题。你提供的链接非常有用。我的情况与“join函数”类似,只是我只想在返回的结果(在我的例子中是docs/docs1)不是空的情况下进行下一次调用。@User cool,很高兴这有帮助。如果您需要以回调样式运行类似的操作(您的第一个示例),请尝试查看。基本上你也可以这样做,但是在常规的回调方式中。你提供的链接非常有用。我的情况与“join函数”类似,只是我只想在返回的结果(在我的例子中是docs/docs1)不是空的情况下进行下一次调用。@User cool,很高兴这有帮助。如果您需要以回调样式运行类似的操作(您的第一个示例),请尝试查看。您基本上也可以这样做,但使用常规回调方式。