鍍金池/ 問答/Linux  HTML/ 如何人為控制JS代碼片段占用主進(jìn)程(Main Thread)的時(shí)間?

如何人為控制JS代碼片段占用主進(jìn)程(Main Thread)的時(shí)間?

我們的Web應(yīng)用規(guī)模比較大,會在后臺(指的還是前端JS運(yùn)行環(huán)境中)進(jìn)行大量的計(jì)算。這就導(dǎo)致用戶的操作,比如touch and move等,感覺到明顯的卡頓。原因是Main Thread被后臺進(jìn)行js的代碼占用了。

我查了很多資料,看到Google的Web開發(fā)建議中,說要把每個(gè)JS任務(wù)的時(shí)長控制在50ms以內(nèi),并且盡可能多的給Main thread留出空閑時(shí)間,以便Main Thread可以去處理用戶輸入性操作。

請問,我該如何控制一個(gè)方法運(yùn)行多久???
是把大的function寫成多個(gè)小function?還是把for循環(huán)之類的改成多久執(zhí)行一次?

有沒有相關(guān)的文章和教程可以學(xué)習(xí)?

多謝各位

回答
編輯回答
小曖昧

不知道你的任務(wù)是什么類型的計(jì)算,樓上已經(jīng)回復(fù)es6的用法,那給你提供另外一種es5的方法吧,你可以試試用setTimeout代替setInterval,比如:

function do() {
  setTimeout(function () {
    /*做點(diǎn)什么*/
    do();
  },0)
}
do();

這樣的好處是讓do每次執(zhí)行都變成一個(gè)異步任務(wù),插入到任務(wù)隊(duì)列中,沒那么容易阻塞進(jìn)程。

2017年10月13日 16:05
編輯回答
愿如初

我補(bǔ)一個(gè)自認(rèn)為最漂亮的方法吧:

const yieldThread = () => new Promise(setTimeout);

async function longTask() {
    for (let i = 0; i < 10000; i++) {
        // do whatever you like

        if (i % 100 === 0) await yieldThread();
    }
}
  • 該如何控制一個(gè)方法運(yùn)行多久?。?br>if (i % 100 === 0)改成Date.now()
  • 是把大的function寫成多個(gè)小function?
    那樣會搞得代碼很丑吧
  • 還是把for循環(huán)之類的改成多久執(zhí)行一次?
    所以寫成上面那樣

估計(jì)肯定有人問,所以提前解釋一下new Promise(setTimeout)

new Promise(setTimeout)
/*等價(jià)于*/ new Promise((...args) => setTimeout(...args))
/*等價(jià)于*/ new Promise((resolve, reject) => setTimeout(resolve, reject))
/*等價(jià)于*/ new Promise((resolve, reject) => setTimeout(resolve, NaN))
/*等價(jià)于*/ new Promise((resolve, reject) => setTimeout(resolve, 0))

因?yàn)槭菐旌瘮?shù),而且反正是自己用,所以可讀性喂狗 :)

2017年9月23日 14:30
編輯回答
兔囡囡

連續(xù)的運(yùn)算時(shí)間不超過300ms, function 拆為多個(gè)小 function 沒用, 你需要利用回調(diào)來拆分長時(shí)間的運(yùn)算.

JS的單線程, 所以你可以通過定時(shí)器來把一個(gè)費(fèi)時(shí)的運(yùn)算拆分為好幾段, 然后運(yùn)算在不同時(shí)段的任務(wù)隊(duì)列循環(huán)中

2017年6月7日 22:40
編輯回答
傻丟丟
function f200() {
    for (let i = 0; i < 200; i++) {
        //doSomething
    }
    
}


function f100() {
    return new Promise((reslove) => {
        setTimeout(() => {//由于Promise屬于microtask 會在一起輪詢里執(zhí)行完所有promise 達(dá)不到異步效果 因此需要setTimeout
            for (let i = 0; i < 100; i++) {
                //doSomething
            }
            reslove('f100');
        }, 0)
    })
}



Promise.all([f100(), f100()]).then(([r1, r2]) => {
    console.log(r1, r2)
})

打個(gè)比方,把一個(gè)進(jìn)行大量的計(jì)算f200,拆成兩個(gè)f100。重點(diǎn)是不能一次執(zhí)行大量同步代碼。

2017年5月7日 05:04