可能的副本 await is only valid in async function。
我是NodeJS
的新手,我发现async-await
的概念有点令人困惑。
经过一番阅读和摸索,这是我对同样的理解。
假设我有一个像这样的函数sum
。
function sum(a, b) {
// print the numbers
for (var i = 0; i < 100000; i++) {
console.log(i);
}
// settimeout
new Promise (resolve => {
setTimeout(resolve, 1000);
});
return a+b;
}
function main() {
let a = sum(5,2);
console.log(a);
}
main();
它为计时器分配一个新线程,并继续正常的流程。它首先打印所有数字,返回7
,然后等待1秒钟后退出。
但是现在我要按行的顺序执行。将await
关键字放在计时器Promise
之前很有意义。
async function sum(a, b) {
// print the numbers
for (var i = 0; i < 100000; i++) {
console.log(i);
}
// settimeout
await new Promise (resolve => {
setTimeout(resolve, 1000);
});
return a+b;
}
问题1:在这里,我不理解使用async
来使用await
的义务。仅放置async
只会使函数返回Promise
而不是值。流量不变。在打印7
之前,它仍会打印所有数字。
问题2:我认为函数前的单词async
会误以为函数调用将是异步的,尽管不是。关于设计有任何澄清吗?
问题3:
NodeJS
中,没有同步或异步功能调用的概念,除非我们有一些阻止功能,例如计时器,远程请求和IO操作。这就是async-await
概念的体现。否则,即使程序具有Promises
,它也只是一个线程。async
只会使其返回Promise
而不是值。它不会改变程序流程。也许,这只是增加了一些额外的机制来处理await
(如果有)只是一个猜测!。async
不一定使任何函数(或其调用)都异步。除非包含另一个async
使其保持等待状态,否则调用具有Promise
关键字的函数仍将是同步的。这就是await
进入的地方。我的理解是否正确?
答案 0 :(得分:3)
您的函数不是一个很好的例子,因为返回值与await
结果没有任何关系。因此,Promise
的使用是无关紧要的,因为没有它就可以重写代码。让我们稍微改变一下功能,以便它实际上在promise中生成结果:
function sumLater(a, b) {
return new Promise(resolve => {
setTimeout(() => resolve(a+b), 1000);
});
}
async function sum(a, b) {
// print the numbers
for (let i = 0; i < 100000; i++) {
console.log(i);
}
// settimeout
let result = await sumLater(a, b);
// using the awaited result
console.log("The awaited result is", result);
return result;
}
async
极大地改变了内部执行函数的方式。一方面,使用承诺的函数无法返回在承诺内生成的值。以同样的方式,任何包含await
的函数都不能返回从await
开始生成的任何内容,而不会将它们包装在promise中。其原因是当前的计算体系结构中缺少时间旅行。如果一个函数可以 now 返回一个将在两个小时后 完成的操作的结果,那将是一个相当不错的突破。
async
不仅向JavaScript引擎发出信号,表明该函数将以这种特殊方式执行,还向人类代码阅读器发出信号,即它返回Promise,而不是返回值(除非返回值)首先已经是一个承诺,不需要包装。
您的大多数问题都归因于术语混乱。不要被术语的字面意义所困扰。 JavaScript中的所有内容(Web Workers除外)都不是同时发生的,乍一看,同时和同步应该是同义词。在JavaScript中,就我所见,同步的意思是“完全在同一任务中执行”,异步的意思是“将新任务放置在执行堆栈中”,或多或少。从这个角度看,async
确实表示该函数将是异步的,因为JavaScript中的含义是“异步”。
答案 1 :(得分:2)
仅使用async-await
做出返回承诺或promise并不会真正使函数异步。 async-await
或promise用于处理Java的真正异步功能。
异步函数只能设置setTimeout,setInterval,requestAnimationFrame和其他函数,有关异步函数的更多信息,请查看这篇文章How to Create asynchronous function in javascript?。
将使用两个示例来说明这一点,一个示例使用async-await
,另一个示例使用promise
,它们之间有什么区别:
```
function main() {
return new Promise( resolve => {
console.log(1);
resolve(true);
});
}
main()
.then( result => { // result will have whatever main promise will resolve.
console.log(2);
});
console.log(3);
```
如果使用promise或返回promise将使函数异步,则输出顺序将为
3
1
2
但是,仅返回promise不会使函数异步,因此输出为
1
3
// Asynchronous happen here
2
现在为什么2后3?,因为只有Javascript异步函数可以异步并进入调用栈,然后进入事件队列,所以.then( function() {})
的回调函数才是javascript的真正异步函数。因此,这种行为。 注意,调用main()会返回一个Promise函数。这将用于Promise和async-await之间的区别。
```
async function main() {
console.log(1);
return true;
}
main()
.then( result => { // Result have whatever main function return.
console.log(2);
});
console.log(3);
```
与此类似,也将打印
1
3
// Asynchronous happen here
2
异步等待和承诺之间有什么区别?
async-await只能使用await
处理promise,并且任何不返回promise并使用回调函数的异步函数(例如setTimeout,setInterval,request.js,https.js函数等)都不能执行用async-await处理。要处理此类函数,我们只能使用Promise,因为Promise使用回调函数,因此可以处理任何异步函数:
function timeout() {
return new Promise( (resolve, reject) => {
console.log(1);
setTimeout( function() {
console.log(2);
resolve(true);
}, 1000);
});
}
async function main() {
console.log(3);
let result = await timeout();
console.log(4);
return result;
}
main()
.then( result => {
console.log(5);
});
console.log(6);
如预期的那样,到达异步函数setTimeout
时,回调函数被推到事件队列并继续处理,再次等待是异步的(不是函数,但其行为类似于.then()
)推送到事件队列。其余所有继续,因此输出为:
3
1
6
// asynchronous happens here
2
4
5
最后一个示例详细说明了有关等待的信息,从上一个示例中删除了setTimeout的使用:
function timeout() {
return new Promise( (resolve, reject) => {
console.log(1);
console.log(2);
resolve(true);
});
}
async function main() {
console.log(3);
let result = await timeout();
console.log(4);
return result;
}
main()
.then( result => {
console.log(5);
});
console.log(6);
预期输出:
3
1
2
6
// Asynchronous await here
4
5
由于async-await等待诺言解析,因此不能与回调异步函数一起使用,否则async-await使代码更清晰漂亮,并减少.then()
的回调链。 Promise必须用于使回调异步函数并防止回调地狱。
答案 2 :(得分:0)
它仍然是javascript,这意味着它们仍在单个线程上运行。 await
关键字在该行暂停async
函数的执行,直到该行可能有一个值解析为止,此时该函数内的执行将继续。您看到所有数字都第一次打印的原因是,该代码在任何异步调用之前。在两个示例中,执行似乎都相同,因为打印100000日志所需的时间比承诺解决所需的时间长得多。