2 回答
TA贡献1852条经验 获得超1个赞
Promise 构造函数是完全同步的(除非你调用其他异步的东西,比如setTimeout或另一个 Promise)。在第二个代码中,同步promiseFunction1运行并立即调用resolve。对promiseFunction2. 因此,创建的第一个 Promise(这里是 from promiseFunction1)将在第二个之前解决,无论每个promiseFunction运行的同步操作可能是昂贵的。
该promiseFunction1承诺立即首先解析,如此这般到microtask队列第一,那么其相关的.then运行第一。
昂贵的同步代码通常不是在主线程上运行的好主意,因为它会阻塞 UI - 如果您遇到这种情况,请考虑将其移至工作线程,如果可能的话。
对于您的第一个代码:
我当时认为每个承诺都是没有顺序保证的并行执行。
因为resolveAfter2Seconds2 秒后resolveAfter1Second解析,1 秒后解析,所以几乎可以保证 1 秒 Promise 将首先解析。
下面的两个代码是一样的吗?
一点也不。首先,promiseFunction当parallel被调用时,两者都会立即运行。在第二种情况下,promiseFunction2仅在promiseFunction1解决后运行。
TA贡献1829条经验 获得超7个赞
说Promise链通常意味着一系列then()调用,明确地意图按顺序运行它们,但是以异步方式,等待步骤之间的某些事件。
而不是编写一系列深入的嵌套回调......
function delay2s(callback){
setTimeout(callback,2000);
}
delay2s(()=>{
log.innerText="1.";
delay2s(()=>{
log.innerText+=" 2.";
delay2s(()=>{
log.innerText+=" 3.";
delay2s(()=>{
log.innerText+=" 4.";
delay2s(()=>{
log.innerText+=" 5.";
delay2s(()=>{
log.innerText+=" and Done.";
});
});
});
});
});
});
<span id="log">Soon</span>
...你可以保持在一个“理智”的水平:
function delay2s(){
return new Promise(resolve=>setTimeout(()=>resolve(),2000));
}
delay2s().then(()=>{
log.innerText="1.";
return delay2s();
}).then(()=>{
log.innerText+=" 2.";
return delay2s();
}).then(()=>{
log.innerText+=" 3.";
return delay2s();
}).then(()=>{
log.innerText+=" 4.";
return delay2s();
}).then(()=>{
log.innerText+=" 5.";
return delay2s();
}).then(()=>{
log.innerText+=" and Done.";
});
<span id="log">Soon</span>
而且拥有多个独立的Promises并不代表它们一起运行,而是它们一起等待。
当然,这种情况下也有一些不错的辅助工具。就像等待一些事件,并在所有事件都完成后做某事可能看起来像一些讨厌的、命名的回调加上一些更讨厌的计数器:
let counter=5;
function tryfinal(){
if(--counter>0)return;
log.innerText+=" all Done.";
}
for(let i=0;i<counter;i++){
setTimeout(()=>{
log.innerText=(log.innerText=="Soon"?"":log.innerText+" ")+(i+1)+".";
tryfinal();
},4000*Math.random());
}
<span id="log">Soon</span>
或者它可以使用Promise.all/Settled():
let promises=[];
for(let i=0;i<5;i++){
promises.push(new Promise(resolve=>setTimeout(()=>{
log.innerText=(log.innerText=="Soon"?"":log.innerText+" ")+(i+1)+".";
resolve();
},4000*Math.random())));
}
Promise.all(promises).then(()=>log.innerText+=" and Done.");
<span id="log">Soon</span>
如果你想积极地并行做一些事情,你需要线程,这意味着web workers。此示例在两个线程上向上计数几秒钟,不时报告进度(在此期间它与 CPU 一起烹饪,您可以检查您所在操作系统的一些性能监控应用程序):
let limit=5000000000;
let report=100000000;
if(limit>Number.MAX_SAFE_INTEGER)
log.innerText="No, you do not want that.";
else {
let workertext="data:text/plain,"
+escape("for(let i=0;i<="+limit+";i++)"
+" if(i%"+report+"===0)"
+" postMessage(i);"
+"postMessage('Done');");
console.log(workertext);
let w1=new Worker(workertext);
let w2=new Worker(workertext);
w1.onmessage=m=>log1.innerText+=" "+m.data;
w2.onmessage=m=>log2.innerText+=" "+m.data;
}
<div id="log1">Worker1: </div>
<div id="log2">Worker2: </div>
旁注:有趣的是,在超出带符号的 32 位整数范围(日志中的 2100000000 -> 2200000000,或实际边界为 2147483647 -> 2147483648)后,计数会变慢。至少在我的 Chrome 中。
添加回答
举报
