亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Javascript - 等待超長循環的正確方法?

Javascript - 等待超長循環的正確方法?

天涯盡頭無女友 2023-07-29 15:36:09
也許這是一個 async/await 情況,但我認為 async 主要用于 api 調用(?)你如何等待一個很長的循環完成,就像這樣:let x;for (i = 1, i < 10000000000000000, i++) {  x += (i * 99999);}console.log(x);
查看完整描述

2 回答

?
人到中年有點甜

TA貢獻1895條經驗 獲得超7個贊

我認為 async 主要用于 api 調用(?)

有兩個與該詞相關的不同概念async

  • async/await函數以同步方式接收 Promises 結果的語法糖

  • 真正的異步行為 XHR api 調用、延遲執行、事件處理

async/awaitfunction 不會自動使您的函數執行異步。

const foo = async (i) => { console.log('foo running', i); return i == 0 ? 42 : await foo(i-1); };

console.log('foo before')

foo(5)

  .then(x => console.log('foo', x))

console.log('foo after')


// foo before

// foo running 5

// foo running 4

// foo running 3

// foo running 2

// foo running 1

// foo running 0

// foo after

// foo 42

JavaScript 是單線程的,所有并發任務必須分成異步塊,以便其他任務有機會工作。


因此,您應該將同步循環拆分為許多異步部分,以免被凍結。


例如(我減少參數以便沒有太多等待時間):


async function calcX() {

  let x = 0;

  function iteration(i) {

    x += (i * 99999);

    if (++i >= 10000) return Promise.resolve(x);

    return new Promise((resolve) => {

      setTimeout(() => iteration(i).then(resolve), 0);

      // or requestAnimationFrame

    });

  }

  return await iteration(1);

}

const start = Date.now();

calcX()

  .then(x => console.log(x, Date.now() - start), err => console.error(err));


// 4999450005000 42465

如果將每次迭代都放入事件循環中,它可能會太慢。所以你可以通過批處理它們來優化它(參見@Steve的答案)


或者使用 WebWorker 來完成繁重的同步任務


查看完整回答
反對 回復 2023-07-29
?
森欄

TA貢獻1810條經驗 獲得超5個贊

您可以通過檢查是否已經過了設定的時間,然后稍后返回該函數,將長時間運行的同步函數轉換為異步函數(在此示例中通過 實現)setTimeout:


var lastBreak = Date.now()


function takeABreak() {

    return new Promise(resolve=>setTimeout(resolve));

}


async function maybeTakeABreak() {

    if (Date.now() - 17 > lastBreak) {

        lastBreak = Date.now();

        await takeABreak();

    }

}


async function myLongLoop() {

    let x = 0;

    for (let i = 1; i < 100000000000000; i++) {

       await maybeTakeABreak();

       x += (i * 99999);

       if (!(i%1000000)) {

          console.log(i);

          // alternatively you could run `await takeABreak();` here

       }

    }

    return x;

}

myLongLoop().then(x=>console.log(x));


查看完整回答
反對 回復 2023-07-29
  • 2 回答
  • 0 關注
  • 194 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號