JavaScript 中的回调、Promises 和 Async/Await
JavaScript 是单线程的,这意味着同一时刻只能发生一件事。同步代码按照编写的顺序从上到下执行。同步代码也是“阻塞”的——每一行代码都会等待上一行代码执行完毕后才能运行。
相比之下,异步代码是“非阻塞”代码,它允许长时间运行的请求不阻塞主 JavaScript 线程。请求完成后,可以执行其他代码。这通常通过以下三种方式之一实现:
- 回调
- 承诺
- 异步/等待
让我们看几个例子,看看如何使用这三种方法编写异步代码。
回调
回调函数是作为参数传递给异步函数的函数。回调函数会在异步部分工作完成后执行。
让我们使用该方法模拟等待 API 请求返回响应setTimeout
。回调方法可能如下所示:
function myAsyncMethod(callback) {
console.log('myAsyncMethod was executed')
setTimeout(callback, 1000)
}
function myCallbackMethod() {
console.log('myCallbackMethod was executed')
}
myAsyncMethod(myCallbackMethod)
这段代码首先会在控制台中打印“myAsyncMethod was performed”。然后等待一秒钟,再在控制台中打印“myCallbackMethod was performed”。
承诺
Promises 是另一种编写异步代码的方式,它可以帮助您避免深度嵌套的回调函数(也称为“回调地狱”)。Promise 可以处于以下三种状态之一:待处理 (pending)、已解决 (resolved) 或已拒绝 (rejected)。Promise 解决后,您可以使用promise.then()
方法来处理响应。如果 Promise 被拒绝,您可以使用 方法来处理错误promise.catch()
。
我们可以使用如下承诺重写前面的示例:
function myAsyncMethod() {
console.log('myAsyncMethod was executed')
return new Promise((resolve, reject) => {
setTimeout(resolve, 1000)
})
}
function myPromiseThenMethod() {
console.log('myPromiseThenMethod was executed')
}
myAsyncMethod().then(myPromiseThenMethod)
和以前一样,此代码将首先在控制台上打印文本“myAsyncMethod 已执行”。然后,它将等待一秒钟,然后再在控制台上打印文本“myPromiseThenMethod 已执行”。
异步/等待
Async/await 是 ES2017 中引入的新语法。它允许你以看似同步的方式编写异步代码,即使它实际上并非同步的。这使得代码更容易理解。
让我们再次重写示例,这次使用 async/await:
function myAsyncMethod() {
console.log('myAsyncMethod was executed')
return new Promise((resolve, reject) => {
setTimeout(resolve, 1000)
})
}
function myAwaitMethod() {
console.log('myAwaitMethod was executed')
}
async function init() {
await myAsyncMethod()
myAwaitMethod()
}
init()
再次,此代码将首先在控制台上记录文本“myAsyncMethod 已执行”。然后,它将等待一秒钟,然后在控制台上记录文本“myAwaitMethod 已执行”。
注意我们是如何init
使用async
关键字来定义函数的。然后,我们await
在调用函数之前使用了关键字来告诉代码,在函数运行完成之前myAsyncMethod
,我们不想运行下一行代码调用。myAwaitMethod
myAsyncMethod
现在我们有了看似同步但实际异步运行的代码!Async/await 为我们提供了两全其美的优势:非阻塞代码,同时仍然易于阅读和理解。
文章来源:https://dev.to/thawkin3/callbacks-promises-and-async-await-in-javascript-44ia