我编写了很多JavaScript代码,尽管我认为我确实理解了promises的工作方式,但我不确定我是否完全理解了承诺给JS世界带来的好处.考虑下面的代码,简单地使用包含调用调用的回调进行异步调用,依此类推.
(function doWorkOldSchool() {
setTimeout(function() {
// once done resolve promise
console.log("work done");
setTimeout(function goHome() {
// once done resolve promise
console.log("got home");
try {
setTimeout(function cookDinner() {
// this exception will not be caught
throw "No ingredients for dinner!";
console.log("dinner cooked");
setTimeout(function goToSleep() {
// once done resolve promise
console.log("go to sleep");
}, 2000);
}, 2000);
} catch (ex) {
console.log(ex);
}
}, 2000);
}, 2000);
}());
我看到的一个问题是:
>回调中抛出的异常是无用的.是否正确的说,当抛出调用发生时,这些抛出调用超出范围,因此异常无法调用并且一直冒泡到顶部?如何处理这种异常?
>第二个问题我看到这个嵌套业务可能会变得非常深,即使你可以在setTimeout代码之外保留回调函数代码,它也可能变得一团糟.
首先,有人可以澄清是否还有其他任何明显的问题或这种编码的优势?
现在,下面我准备的程序真的做了同样的事情,但这次使用promises:
function doWork() {
return new Promise(function(res, rej) {
// do your asynchronous stuff
setTimeout(function() {
// once done resolve promise
res("work done");
}, 2000);
});
}
function goHome(succ) {
console.log(succ);
return new Promise(function(res, rej) {
// do your asynchronous stuff
setTimeout(function() {
// once done resolve promise
res("got home");
}, 2000);
});
}
function cookDinner(succ) {
console.log(succ);
//if exception thrown here it will be caught by chained err handler
throw "No ingredients for dinner Exception!";
return new Promise(function(res, rej) {
// do your asynchronous stuff
setTimeout(function() {
// something went wrong so instead of using throw we reject the promise
rej("No ingredients for dinner!");
// once done resolve promise
}, 2000);
});
}
function goToSleep(succ) {
console.log(succ);
return new Promise(function(res, rej) {
// do your asynchronous stuff
setTimeout(function() {
// once done resolve promise
res("zzz... zz..");
}, 2000);
});
}
doWork()
.then(goHome)
.then(cookDinner)
.then(goToSleep)
.then(function(succ) {
console.log(succ);
}, function(err) {
console.log(err);
});
与之前的解决方案相比,我发现这种方法没有明显的问题,除了你显然必须理解承诺编码/维护这个东西.然而,优点是:
>抛出的异常INSIDE OF处理程序将被捕获在更进一步链接的错误处理程序中.
>被拒绝的Promise将被链式错误处理程序捕获
>代码更清洁
现在,我的理解是正确的还是每种方法都有其他优点/缺点?
解决方法:
您的代码使用了一些反模式,您永远不应该在应用程序代码中创建承诺(例如,通过新的Promise,“deferreds”等).你也必须永远不要将回调与promises混合,因为这样你就会失去异常冒泡(承诺点)并使你的代码变得非常冗长.
您可以使用库或自己实现延迟:
function delay(ms, val) {
return new Promise(function(res){setTimeout(res.bind(null, val), ms);});
}
然后:
function doWork() {
return delay(2000, "work done");
}
doWork()
.then(function(succ) {
console.log(succ);
return delay(2000, "got home");
})
.then(function(succ) {
console.log(succ);
// Never throw strings, yet another anti-pattern
throw new Error("No ingredients for dinner Exception!");
// Pointless to add code after throw
})
.then(function(succ) {
return delay(2000, "zzz.. zz..");
})
// Don't use the second argument of .then, use .catch
.catch(function(err) {
console.log("error: ", err);
});
为什么要使用.catch而不是第二个参数?那么,与你同步编写它的方式相比:
try {
doWork();
console.log("work done");
sleep(2000);
console.log("got home");
sleep(2000);
throw new Error("No ingredients for dinner Exception!";)
sleep(2000);
console.log("zzz.. zz..");
}
catch(e) {
console.log("error: ", err);
}
得到它?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。