考慮下面的兩個函式,都是異步的,一個是需要大量時間的殘酷作業負載,另一個是等待函式,它通過設定超時來等待精確的秒數。
async function Brutal_Workload()
{
for(var x = 0; x< 1000 * 1000 * 1000; x )
{
}
}
async function Time_Wait(seconds)
{
var promise = new Promise((resolve, reject) =>
{
var msecs = Math.floor(seconds * 1000);
var timer =
setTimeout(
function()
{
clearTimeout(timer);
resolve();
},
msecs);
});
return promise;
}
現在,讓我們呼叫 setInterval 回圈中的第一個函式
setInterval(
async function()
{
await Brutal_Workload();
console.log("BLIP");
}, 1000 / 30);
一切如預期:盡管間隔以每秒 30 次呼叫的速度運行,但我每秒只收到 1 個信號,因為 Brutal_Workload 正在阻塞它。
但是當我使用其他功能時......
setInterval(
async function()
{
await Time_Wait(1);
console.log("BLIP");
}, 1000 / 30);
我每秒得到 30 個 BLIP。Time_Wait 函式在 setInterval 之外作業正常,但在這里似乎不起作用。
知道什么可能導致這種行為嗎?
uj5u.com熱心網友回復:
好的,與其繼續在評論中來回討論,我只是將其作為答案發布。
Javascript 既是單執行緒又是并發的。我知道你知道這一點,但你似乎沒有意識到其中的含義。在你的第一個函式中,你只會console.log經常看到一個,因為你的“殘酷的作業量”會阻塞唯一的執行執行緒直到它完成,這意味著無論你傳遞給哪個數字,setInterval不僅沒有其他呼叫運行,下一位作業甚至沒有排隊等待運行,因為您殘酷的作業負載正在阻塞唯一的執行執行緒。
請理解,運行時環境與您的setInterval代碼在同一(唯一)執行緒上運行,JS 引擎不會欺騙并在一個執行緒和另一個執行緒中運行您的東西。因此,雖然殘酷的作業負載正在做它的事情,但它本身,更不用說你傳遞給它的功能,根本沒有運行。就我們在??這里的討論而言,在 Promise 中使用和包裝您的殘酷作業負載基本上是零差異,因為殘酷的作業負載占主導地位。setIntervalsetIntervalasync
所以這解釋了第一個例子,到目前為止一切順利。在第二個。
與第一個示例不同,第二個示例中沒有長時間運行的代碼塊來占用執行執行緒。所以你的回呼setInterval運行,盡職盡責地注冊一個要在一秒鐘內運行的東西,并產生對執行執行緒的控制,這也是第一個例子沒有(也不能做)的事情。這里的 Promise 和async/await實際上確實啟用并發,這在第一個示例中無法做到,因為殘酷的作業負載占用了執行緒。因此,在幾分之一秒內您的回呼setInterval將再次運行,盡職盡責地排隊等待另一件事在一秒鐘后運行,依此類推。
因此,在約 1 秒后,第一個排隊的日志發生,然后在幾分之一秒后發生第二個,然后依此類推。這在第一個示例中沒有發生,因為盡管您告訴setInterval您運行 30 次/秒,但殘酷的作業負載意味著它setInterval 本身無法運行,甚至無法將您的回呼排隊等待運行。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/537064.html
下一篇:為什么Rc在異步fn中作業
