回调、承诺和异步/等待
回调、承诺和异步/等待
source: 自由派
我目前正在更深入地研究 JS 的工作原理,并且我一直在观看 Will Sentance 的 JavaScript: The Hard Parts 课程 .其中一个部分是关于 Promises 和 Async/Await 的,我不得不说这对我来说仍然有点神秘,所以在观看了课程的部分之后,我决定我想多读一些关于它的内容MDN 文档。
我认为首先,回调是有意义的,看看它是如何通过承诺改进的,并使我们的生活更轻松。
回调
函数在另一个函数中作为参数传递,然后在该函数中调用以执行任务。
console.log('第一');
console.log('第二');
设置超时(()=>{
console.log('第三');
},2000);
console.log('最后一个');
此代码段将返回:
第一的
第二
最后的
第三
这是因为 setTimeout 设置为等待 2 秒,因此执行威胁将继续,然后再返回。在您需要进行多次调用之前,此方法很好,为此您必须嵌套函数以获得所需的行为。这将导致最终进入所谓的回调地狱或末日回调金字塔。
承诺
MDN 文档将 Promise 定义为表示异步操作最终完成或失败的对象。
Promise 是一个返回的对象,您将回调附加到该对象,而不是将回调传递给函数。
为什么要使用它们?
使用 Promise 将保证你得到一些你不会从回调中得到的结果,例如:
- 如果回调添加了
。然后()
它会 永远不会被调用 在当前之前 事件循环运行 已经 完全的 . - 回调将是 被调用 即使他们是 之后添加 这 异步操作 承诺所代表的成功或失败。
- 你可以加 多个回调 只需调用
。然后()
几次。它们将按照您在代码块中放置它们的顺序依次调用。 - 链接 ,这值得更详细地介绍。
链接
当您需要执行多个连续的异步操作并且每个后续操作在前一个操作成功时开始时,就会发生链接。在承诺链中 然后()
返回一个新的承诺,与原来的不同。
现在,我们将回调附加到返回的 Promise 上,形成一个 Promise 链。
请记住,您也可以在捕获后进行链接。
新的承诺((解决,拒绝)=> {
console.log("开始");
解决();
})
.then(() => {
throw new Error("出了点问题");
console.log("这是第一次");
})
.catch(() => {
console.error("这一秒");
})
.then(() => {
console.log("不管发生什么都要这样做");
});
重要的 : 总是 返回
结果 ,否则回调将无法捕获先前承诺的结果。如果前一个处理程序启动了一个 Promise 但没有返回它,则无法再跟踪它,并且该 Promise 被称为“浮动”。如果您有比赛条件,情况可能会变得更糟,因为下一个读数可能不完整。
虽然在回调中我们必须多次跟踪错误,但在 Promise 中,如果出现错误,浏览器将转到 。抓住()
堵塞。
尝试 {
常量结果 = syncDoSomething();
const newResult = syncDoSomethingElse(result);
const finalResult = syncDoThirdThing(newResult);
console.log(`得到了最终结果:${finalResult}`);
} 捕捉(错误){
失败回调(错误);
}
这与同步代码的工作方式非常相似,因此它与异步代码的相似之处在于 异步/等待 句法。
异步函数 foo() {
尝试 {
常量结果 = 等待 doSomething();
const newResult = await doSomethingElse(result);
const finalResult = 等待 doThirdThing(newResult);
console.log(`得到了最终结果:${finalResult}`);
} 捕捉(错误){
失败回调(错误);
}
}
异步/等待
的目的 异步
和 等待
是通过使异步代码看起来像同步代码来简化使用 Promise 的异步代码(见上文)。
这将使从一系列连续的异步函数调用构建操作变得更加容易,避免了创建显式承诺链的需要,并允许您编写看起来像同步代码的代码。
即使异步函数的返回值表现得好像它被包裹在一个 Promise.resolve,
它们不等价。
异步函数将返回不同的引用,但 Promise.resolve
* 如果给定值是一个承诺,则返回相同的引用。
* Promise.resolve
解决 Promise 的给定值,如果该值是 Promise,则返回该 Promise。
当您想要检查 Promise 的相等性和异步函数的返回值时,这种差异可能会导致问题。
请记住,就像 Promise 链一样,await 强制异步操作按顺序完成。如果下一个操作的结果取决于前一个操作的结果,则这是必要的,但如果不是这种情况,请使用 承诺.all()
会更有效率。
总而言之,Promise 解决了我们使用回调结构面临的一个基本问题。它们允许我们链接并简化捕获所有错误,甚至是抛出的异常和编程错误。
Async/await 通过使它看起来像同步代码来简化异步代码的工作,记住它会返回一个与可能导致问题的 promise 不同的引用。
感谢阅读,感谢您的宝贵时间。如果您需要任何帮助或有任何问题,请联系我们!
如果您有任何问题,请随时给我留言 领英 或发给我一个 电子邮件 .
祝你今天过得愉快!
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明