根据MDN,
异步函数声明定义了异步函数
我理解它,因为该功能将被视为异步过程,就像setTimeout
或某些数据库请求一样。例如,在下面的示例中,该过程应在数字之间的某个位置输出“ main”。
let func2 = async () => {
for (let i = 0; i < 51; i ++) {
console.log(i);
}
}
(async () => {
func2();
console.log("main");
})()
但是,就像整个过程是同步的一样,“ main”总是在最后被控制台。我理解错了什么?
如果同步代码仍处于同步状态,async
的目的是什么?仅允许其中的await
并提供某种奇特的方式来返回Promise
?
答案 0 :(得分:4)
异步是否使其中的所有内容都是异步的?
不。它不是。函数中的代码仍将同步运行,并在运行时阻止事件循环。
如果同步代码仍处于同步状态,异步的目的是什么?只允许在其中等待并提供一些幻想的方式来返回Promise?
是的,它主要用于await
。
但是,在某些情况下,它会自动用承诺包装代码,这一点很有用。例如,它会自动捕获所有抛出的异常,并将其转变为被拒绝的承诺。有时这很有用。有关其他用途的示例,请参见本文的“错误处理”部分:6 Reasons Why JavaScript’s Async/Await Blows Promises Away。
但是,async
关键字的主要功能是定义一个可以使用await
的功能。这就是ES7的设计者决定使await
工作的方式。
仅供参考,如果函数中有一个await
在等待一个诺言,那么这将导致该函数在await
的某个点早返回。它将在那时返回并返回承诺。您正在等待的操作将已经开始,并且直到解决了等待的诺言之后,该功能的其余部分才会执行。因此,使用await
会使某些代码稍后执行。但是,与await
之前的代码一样,即使函数在await
解决之后恢复运行,该函数中的Javascript仍将保持同步和阻塞状态(直到另一个await
或直到return
)。
将其包装在Promise中并检测何时使用.then()
会在调用.then()
处理程序时推迟到事件循环的下一个滴答声为止。因此,.then()
会稍有延迟,因为您将其包装在promise中,然后使用了.then()
,但是代码运行的时间不变。它仍然是同步和阻塞的。
在Javascript中,获取同步代码并使之异步的唯一方法是:
在另一个进程中运行,并使用进程间通信来传达结果。
在使用本机线程或某些其他OS异步接口来执行实际工作的本机代码插件中重写代码,然后从您的插件中为Javascript提供异步接口。 on(通常是一个返回承诺或通过回调通知完成的接口)。现在这是诸如fs.readFile()
之类的node.js异步功能。他们有一个本机代码实现,该实现立即返回,然后在实现中使用本机线程并通过回调通知完成。
使用一些node.js插件为您完成一些任务。有些插件旨在提供线程。
在节点版本10.5 + 中使用node.js线程,并根据其要求进行限制。这是有关该主题的文章:Threads in Node 10.5.0: a practical intro
答案 1 :(得分:4)
否,异步函数内的主体在调用时会运行,但会暂停await
表达式。如果await
没什么可做的,则该函数将像普通函数一样运行,不同之处在于它返回了promise。
但是,如果有await
,执行将暂停并且事件循环将继续。当前事件循环结束后的某个时间里,当等待的约定解决时,它将在中断的地方继续进行。例如,比较此处记录“主”的时间与您的示例。
let func2 = async () => {
console.log("Start")
for (let i = 0; i < 10; i ++) {
if(i == 5) {
await new Promise(resolve => setTimeout(resolve, 200))
}
console.log(i);
}
}
(async () => {
func2().then(() => console.log('done'));
console.log("main");
})()
考虑async
函数的另一种方法是考虑它们与generators的关系。我喜欢将await
视为一种yield
。例如,为了达到相同的行为,我们只需更改func2
的主体,就是将await
换成yield
:
function* func2() {
console.log("Start")
for (let i = 0; i < 10; i++) {
if (i == 5) {
yield new Promise(resolve => setTimeout(resolve, 0))
}
console.log(i);
}
return "done"
}
let gen = func2()
gen.next().value.then(() => console.log(gen.next().value))
console.log("main")
async
/ await
只是使这变得更容易,对于常见用例也更加直观。