rb6*_*612 9 javascript promise
我试图更好地掌握JS中的异步功能和诺言。为此,我编写了一个示例程序,其目标是调用一个可以完成繁忙工作的函数(有意不使用异步,setTimeout因为我想模仿长时间运行的进程),但立即返回。但是,我似乎无法弄清楚为什么它不起作用。
test();
async function intense(){
var start = new Date().getTime();
for (var i = 0; i < 1e6; i++) {
if ((new Date().getTime() - start) > 2000){
break;
}
}
console.log("Done with async work");
}
async function test(){
console.log("Print 1");
intense(); // does some busy work for a few seconds
console.log("Print 2"); // want this to print immediately after print 1
}Run Code Online (Sandbox Code Playgroud)
当我运行它时,我得到:
Print 1
Done with async work
Print 2
Run Code Online (Sandbox Code Playgroud)
我希望它是:
Print 1
Print 2
Done with async work
Run Code Online (Sandbox Code Playgroud)
我认为它将打印后一个序列,因为我宣布了该函数intense()为异步函数,因此它将立即返回一个Promise并继续异步工作。
我什至试图将intense功能重构为一个立即解决的承诺,但无济于事。
async function intense(){
return new Promise((resolve)=> {
resolve();
var start = new Date().getTime();
for (var i = 0; i < 1e6; i++) {
if ((new Date().getTime() - start) > 2000){
break;
}
}
console.log("Done with async work");
}, null)
}
Run Code Online (Sandbox Code Playgroud)
我想念什么?
T.J*_*der 11
您看到的原因有两个:
一个async函数一直同步到第一个await或第一个return,直到整个函数运行,然后返回您的情况。
忙等待不是异步的。
testawait如果需要等待intense完成才能继续使用。
将某些东西变成承诺并不能使它脱颖而出。在大多数JavaScript环境(包括浏览器)中,这样做的唯一方法是使用Worker线程(MDN,Node.js文档 -Node.js Worker自〜v10.5起就拥有了,尽管它仍被标记为“实验性”的主要部分) API应该相当稳定,因为它们是从网络工作者标准API中提取的)。
重要的是要记住,promise不会使任何东西异步¹,它们提供了一种观察已经异步的结果的方法。
这是一个setTimeout用于异步部分的示例,可以帮助您更好地理解这些内容:
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function intense(value) {
console.log("intense(" + value + ") - This is synchronous");
await delay(100);
console.log("intense(" + value + ") - This is asynchronous, because it's after `await`");
}
async function test(){
console.log("Print 1");
intense(1); // <== WITHOUT await
console.log("Print 2");
await intense(2); // <== With await
console.log("Print 3");
}
test();Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper {
max-height: 100% !important;
}Run Code Online (Sandbox Code Playgroud)
¹有一个小警告:传递给then,catch或的处理程序finally将始终被异步调用,即使您要调用它们的诺言已经得到解决。从字面上看,这实际上是使异步成为唯一的承诺。
因此它将立即返回promise,并继续异步工作。
不,它不会。传递给Promise构造函数的回调被立即调用。异步是调用resolve或reject后续调用的过程,以及.then何时链被调用回。
但是,从代码在另一个线程上运行或被推迟的角度来看,它不是异步的,因为JS本身在单个线程中执行*,所以不会发生。
console.log(1);
const promise = new Promise((resolve, reject) => {
console.log(2); // gets executed immeadiately
});
promise.then(() => console.log(4)); // < Promise resolve asynchronously
console.log(3);
Run Code Online (Sandbox Code Playgroud)
*如果您打算进行真正的“强烈”工作,那么在另一个线程中进行操作可能会有所帮助(请参阅WebWorker浏览器和child_process.spawnNodeJS)。