Javascript 包装现有API';s收回承诺,以避免;“地狱”;?
因此,在这一点上,承诺作为“最佳实践”似乎比回调更有吸引力,但许多现有库仍然使用回调 因此,给定一个已经实现如下回调模式的库:Javascript 包装现有API';s收回承诺,以避免;“地狱”;?,javascript,node.js,promise,Javascript,Node.js,Promise,因此,在这一点上,承诺作为“最佳实践”似乎比回调更有吸引力,但许多现有库仍然使用回调 因此,给定一个已经实现如下回调模式的库: library.connect(function(err) { library.someQuery({}).exec(function(err, result) { // some code library.someQuery(result).exec(function(err2, result2) { // some code
library.connect(function(err) {
library.someQuery({}).exec(function(err, result) {
// some code
library.someQuery(result).exec(function(err2, result2) {
// some code
})
})
})
将这些回调封装在承诺中以避免嵌套是否有好处
new Promise((resolve, reject) => {
library.connect(function(err) {
if (err) reject(err)
else resolve()
}
}).then(() => {
return new Promise((resolve, reject) => {
library.someQuery({}).exec((err, result) => {
if (err) reject(err)
else resolve(result)
}
})
}).then((result) => {
return new Promise((resolve, reject) => {
library.someQuery(result).exec(function(err2, result2) {
if (err) reject(err2)
else resolve(result2)
}
}).then((result) => {
// some code
}).catch((err) => // handle error)
没有嵌套会更好,但要详细得多。我也不确定这会有多大的额外好处。也许更好的错误处理方式?在您的第一个代码片段中,您有多个位置来处理错误,而在承诺中,您只有一个位置 我认为您做了一些很好的观察,而且在使用承诺的情况下,在性能方面会有轻微的开销。但是,如果您能够生活在重复的代码中,那么使用它们可能会获得更容易调试的代码 您也可以创建一个小函数来抽象承诺,但请记住这会增加一点开销:
// Non tested code, but hopes it shows a point
function make_promisable(context, method) {
return new Promise((resolve, reject) => {
context[method]((err, result) => {
if (err) reject(err);
else resolve(result);
});
});
};
//注意:下面的代码实际上似乎隐藏了代码中的逻辑,
//这是好的,还是更难阅读/调试?
使可用(库,'connect')。然后(()=>{
返回make_promisable(library.someQuery({}),'exec');
})。然后((结果)=>{
返回make_promisable(library.someQuery(result),'exec');
})。然后((结果)=>{
//一些代码
}).catch((err)=>//句柄错误)
在您的第一个代码片段中,您有多个位置来处理错误,而承诺只有一个位置
我认为您做了一些很好的观察,而且在使用承诺的情况下,在性能方面会有轻微的开销。但是,如果您能够生活在重复的代码中,那么使用它们可能会获得更容易调试的代码
您也可以创建一个小函数来抽象承诺,但请记住这会增加一点开销:
// Non tested code, but hopes it shows a point
function make_promisable(context, method) {
return new Promise((resolve, reject) => {
context[method]((err, result) => {
if (err) reject(err);
else resolve(result);
});
});
};
//注意:下面的代码实际上似乎隐藏了代码中的逻辑,
//这是好的,还是更难阅读/调试?
使可用(库,'connect')。然后(()=>{
返回make_promisable(library.someQuery({}),'exec');
})。然后((结果)=>{
返回make_promisable(library.someQuery(result),'exec');
})。然后((结果)=>{
//一些代码
}).catch((err)=>//句柄错误)
这主要是观点,但:
- 如果您不止一次这样做,那么可能值得为库编写一个公开基于
的API的外观:
import library from 'library'; export default { connect() { return new Promise((resolve, reject) => { library.connect(function(err) { if (err) reject(err) else resolve() } } } // etc }
- 回调地狱/嵌套是一个实现问题,而不是回调的基本问题,通常可以通过分解函数而不是嵌套来改进。图书馆喜欢让回调像承诺一样清晰,或者更清晰
- promises的一个优点是可以使用语法(假设Babel transpiling)。在实践中,我发现这种语法很棘手,但有些人真的很喜欢它
- 如果您不止一次这样做,那么可能值得为库编写一个公开基于
的API的外观:
import library from 'library'; export default { connect() { return new Promise((resolve, reject) => { library.connect(function(err) { if (err) reject(err) else resolve() } } } // etc }
- 回调地狱/嵌套是一个实现问题,而不是回调的基本问题,通常可以通过分解函数而不是嵌套来改进。图书馆喜欢让回调像承诺一样清晰,或者更清晰
- promises的一个优点是可以使用语法(假设Babel transpiling)。在实践中,我发现这种语法很棘手,但有些人真的很喜欢它
- 这主要是观点,但:
callbackToPromiseCallbacks(resolve,reject){return(err,res)=>err?reject(err):resolve(res);}
来减少样板代码。还有其他避免回调地狱的方法,例如可重用的命名回调。承诺并不能避免回调,它们只是将其压扁,在某些情况下还将其整合。在我看来,使用承诺的关键好处是更好地处理错误。在你的第一个代码片段中,你有很多地方可以处理错误,而承诺只有一个地方。@dev null是的,我认为这是一个可能的答案。还有其他好处吗?或者可能是使其不那么冗长的方法?您可以创建helper函数callbackToPromiseCallbacks(resolve,reject){return(err,res)=>err?reject(err):resolve(res);}
来减少样板代码。还有其他避免回调地狱的方法,例如可重用的命名回调。承诺并不能避免回调,它们只是将其压扁,在某些情况下还将其整合。在我看来,您从转向承诺中获得的关键好处是更好地处理错误。