最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript的宏任務(wù)和微任務(wù)示例詳解

 更新時間:2026年03月17日 09:00:57   作者:辰風(fēng)沐陽  
在JavaScript中宏任務(wù)和微任務(wù)是任務(wù)隊列中兩個不同的任務(wù)類型,它們是JavaScript異步編程機制的重要組成部分,這篇文章主要介紹了JavaScript宏任務(wù)和微任務(wù)的相關(guān)資料,需要的朋友可以參考下

1. 前言

在 JavaScript 中,任務(wù)可以分為同步任務(wù)、異步任務(wù),而異步任務(wù)又進(jìn)一步細(xì)分為宏任務(wù)和微任務(wù)

  • 同步任務(wù):指那些在主線程上排隊執(zhí)行的任務(wù),只有前一個任務(wù)執(zhí)行完畢后,才能開始執(zhí)行下一個任務(wù)
  • 異步任務(wù):異步任務(wù)不會進(jìn)入主線程,而是進(jìn)入 “任務(wù)隊列” 中等待執(zhí)行

JavaScript 語言本身是單線程,這意味著在任何時刻,JavaScript 引擎中只有一條主線程來處理所有的任務(wù)

2. 同步任務(wù)

同步任務(wù)只有前一個任務(wù)執(zhí)行完畢后,才能開始執(zhí)行下一個任務(wù),特點是按照順序執(zhí)行,會阻塞后續(xù)代碼的執(zhí)行

console.log(1);
console.log(2);

3. 異步任務(wù)

異步任務(wù)是只有當(dāng)主線程上的同步任務(wù)全部執(zhí)行完畢后,才會從任務(wù)隊列中取出異步任務(wù)進(jìn)入主線程執(zhí)行

console.log(1); // 同步任務(wù)
setTimeout(() => console.log(3), 0) // 異步任務(wù),等待同步任務(wù)執(zhí)行完畢之后,才會執(zhí)行
console.log(2); // 同步任務(wù)

宏任務(wù)

宏任務(wù)是由宿主環(huán)境發(fā)起的異步任務(wù),通常包含較長的等待時間或需要等待 I/O 操作完成

常見的宏任務(wù):setTimeout / setInterval、ajax 請求、dom 事件

微任務(wù)

微任務(wù)通常用于處理 Promise 或其他需要盡快執(zhí)行的操作

常見的微任務(wù):Promise.then、async / await

setTimeout(() => console.log('定時器 - 宏任務(wù)'), 0)
Promise.resolve().then(value => {
    console.log('Promise - 微任務(wù)');
})
console.log('123 - 同步任務(wù)')
// 123 - 同步任務(wù)
// Promise - 微任務(wù)
// 定時器 - 宏任務(wù)

4. 定時器的任務(wù)編排

在 JavaScript 中,setTimeout 函數(shù)的延時時間的最小值通常是 4 毫秒

這是因為在某些瀏覽器或操作系統(tǒng)中,為了優(yōu)化性能和節(jié)能,定時器的實際執(zhí)行可能會有一定的最小延遲

// 即使設(shè)置了非常小的延時,瀏覽器也可能不會立即執(zhí)行定時器回調(diào)函數(shù),而是等待至少 4 毫秒后才執(zhí)行
setTimeout(() => console.log('定時器'), 0)

設(shè)置定時器延時 200 毫秒執(zhí)行,那么它真的就會 200 毫秒后立即執(zhí)行嗎 ?通過以下代碼可以發(fā)現(xiàn)并不是這樣的

代碼解析原因:因為定時器是異步任務(wù),for 循環(huán)是同步任務(wù),所以定時器要等 for 循環(huán)執(zhí)行完之后才會執(zhí)行定時器

定時器的任務(wù)編排原理:到達(dá)延時時間會先將其放到宏任務(wù)隊列中,等待主線程處理完同步任務(wù),再來處理異步任務(wù)

console.log(new Date().getTime() / 1000);
setTimeout(() => {
    console.log('定時器:' + new Date().getTime() / 1000);
}, 200)
console.log('同步任務(wù)')
for (let i = 0; i < 20000; i++) {
    console.log('');
}

5. Promise 微任務(wù)處理邏輯

Promise 是微任務(wù)中的典型代表,Promise 的構(gòu)造函數(shù)代碼是立即執(zhí)行的,也就是說它是同步代碼

// 4. 定時器,放入宏任務(wù)隊列
setTimeout(() => console.log('定時器'))

new Promise(resolve => {
    // 1. 這里是 promise 的構(gòu)造函數(shù),它是同步代碼
    console.log('promise');
    resolve()
}).then(() => {
    // 3. 這里的代碼會放到微任務(wù)隊列
    console.log('then');
})

// 2. 同步代碼
console.log('hello');

// 由于任務(wù)執(zhí)行順序是:同步任務(wù) > 微任務(wù) > 宏任務(wù),所以上面代碼的輸出順序為
// promise
// hello
// then
// 定時器

如果在定時器內(nèi)部再放入 Promise 和 定時器,那么執(zhí)行順序是怎么樣的 ?

setTimeout(() => {
    // 1. 同步代碼
    console.log('定時器')
    // 因為它是在定時器內(nèi)部,所以它在宏任務(wù)執(zhí)行之后才會放入任務(wù)隊列,才會執(zhí)行
    new Promise(resolve => {
        // 2. 同步代碼
        console.log('timeout promise');
        resolve()
    }).then(() => {
        // 3. 微任務(wù)
        console.log('timeout then');
    })
    // 4. 宏任務(wù)
    setTimeout(() => console.log('定時器內(nèi)部的定時器'))
})
new Promise(resolve => {
    console.log('promise');
    resolve()
}).then(() => {
    console.log('then');
})
console.log('hello');

// 其實很簡單,在上一段代碼的結(jié)果上,繼續(xù)按照任務(wù)執(zhí)行優(yōu)先順序執(zhí)行
// promise
// hello
// then
// 定時器
// timeout promise
// timeout then
// 定時器內(nèi)部的定時器

6. DOM 渲染任務(wù)

瀏覽器在解析頁面時,也是按照順序從上往下解析的,如下所示,先解析 utils.js,然后再渲染 h1 標(biāo)簽

也可以理解為先將解析 utils.js 的任務(wù)執(zhí)行完,再執(zhí)行渲染 h1 標(biāo)簽的任務(wù)

<head>
    <script src="./utils.js"></script>
</head>
<body>
    <h1>JavaScript 的宏任務(wù)和微任務(wù)</h1>
</body>

如果執(zhí)行 utils.js 的時間比較長,那么頁面將遲遲不渲染,進(jìn)入頁面會有較長時間的空白內(nèi)容

for (let index = 0; index < 5000000; index++) {
    document.write(' ')
}

我們可以將 utils.js 的引入放到內(nèi)容渲染后面,改變?nèi)蝿?wù)的執(zhí)行順序,進(jìn)入頁面就不會有長時間的空白了

<body>
    <h1>JavaScript 的宏任務(wù)和微任務(wù)</h1>
    <script src="./utils.js"></script>
</body>

7. 任務(wù)共享內(nèi)存

任務(wù)共享內(nèi)存是指多個任務(wù)可以訪問同一塊內(nèi)存區(qū)域

多個定時器設(shè)置相同時間延時執(zhí)行,它們并不會同時執(zhí)行,而是到達(dá)設(shè)定的時間后將它們放入任務(wù)隊列,依次執(zhí)行任務(wù)

let i = 0
setTimeout(() => {
    // 宏任務(wù)
    console.log(++i);
}, 1000)
setTimeout(() => {
    // 宏任務(wù)
    console.log(++i);
}, 1000)

8. 進(jìn)度條實例體驗任務(wù)輪詢

先寫好一個進(jìn)度條的樣式

<head>
    <style>
        .container {
            width: 200px;
            border-radius: 3px;
            border: 1px solid #ccc;
        }

        #progress {
            width: 0%;
            color: #fff;
            text-align: center;
            background-color: #376de1;
        }
    </style>
</head>

<body>
    <div class="container">
        <div id="progress">0</div>
    </div>
</body>

定時器其實就是往任務(wù)隊列中不斷的放入任務(wù),到達(dá)執(zhí)行時間后,交由主線程依次執(zhí)行任務(wù)

function handle() {
    let i = 0;
    (function run() {
        if (++i <= 100) {
            progress.innerHTML = i
            progress.style.width = i + '%'
            setTimeout(run, 50)
        }
    })();
}
handle()

9. 任務(wù)拆分為多個子任務(wù)

現(xiàn)有以下代碼,前面的累加函數(shù)需要較長時間才能執(zhí)行完成,阻塞了后面代碼的運行,我們來看一下怎么解決這個問題

let count = 0
let num = 987654321
function task() {
    for (let i = 0; i < num; i++) {
        count += num--
    }
    console.log(count);
}
task() // 同步任務(wù)
console.log('hello'); // 同步任務(wù),需要等待 task() 執(zhí)行完后才能執(zhí)行

思路是將大量的計算放入異步任務(wù),讓同步任務(wù)先執(zhí)行,以免造成阻塞

let count = 0
let num = 10000000
function task() {
    // 首次調(diào)用先累加一次
    for (let i = 0; i <= num; i++) {
        if (num <= 0) break;
        count += num--
    }
    if (num > 0) {
        // 后續(xù)累加,放入宏任務(wù)執(zhí)行
        setTimeout(task)
    } else {
        console.log(count)
    }
}
task()
console.log('hello')

10. Promise 微任務(wù)處理復(fù)雜邏輯

將定時器放入 Promise 也可以處理復(fù)雜邏輯,不影響同步任務(wù)的執(zhí)行,但下面用的還是宏任務(wù)(定時器)

let count = 0
let num = 987654321

// 由于 promise 里面的代碼是同步執(zhí)行的,在里面直接寫循環(huán)還是會卡住,所以可以寫個定時器
function task() {
    return new Promise(resolve => {
        let count = 0
        setTimeout(() => {
            for (let i = 0; i < num; i++) {
                count += num--
            }
            resolve(count)
        })
    });
}
async function getSum(num) {
    let res = await task(num)
    console.log(res);
}
getSum(num)
console.log('hello');

因為 Promise 的 then 回調(diào)方法是微任務(wù),那么我們可以將代碼調(diào)整為:

let num = 987654321
async function getSum(num) {
    let res = await Promise.resolve().then(_ => {
        let count = 0
        for (let i = 0; i < num; i++) {
            count += num--
        }
        return count
    })
}
getSum(num)
console.log('hello');

總結(jié) 

到此這篇關(guān)于JavaScript宏任務(wù)和微任務(wù)示例詳解的文章就介紹到這了,更多相關(guān)JS宏任務(wù)和微任務(wù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JavaScript實現(xiàn)數(shù)值自動增加動畫

    JavaScript實現(xiàn)數(shù)值自動增加動畫

    這篇文章主要為大家詳細(xì)介紹了JavaScript實現(xiàn)數(shù)值自動增加動畫,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • javascript放大鏡效果的簡單實現(xiàn)

    javascript放大鏡效果的簡單實現(xiàn)

    這篇文章主要是對javascript放大鏡效果的簡單實現(xiàn)進(jìn)行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2013-12-12
  • 詳解JavaScript的內(nèi)置對象

    詳解JavaScript的內(nèi)置對象

    本文對JavaScript對象的屬性、對象的方法、對象的屬性、訪問對象屬性的語法進(jìn)行了實例分析介紹,有需要的朋友可以看下
    2016-12-12
  • JavaScript?中的時間戳操作和使用詳解

    JavaScript?中的時間戳操作和使用詳解

    時間戳在編程中有著非常廣泛的應(yīng)用,比如記錄事件發(fā)生的時間、計算時間差、生成唯一的標(biāo)識符等,時間戳的使用非常重要,今天我們將一起來探討如何在?JavaScript?中獲取和操作時間戳,感興趣的朋友一起看看吧
    2025-06-06
  • js漂浮廣告實現(xiàn)代碼

    js漂浮廣告實現(xiàn)代碼

    js漂浮廣告實現(xiàn)代碼,本質(zhì)上就是一個來回滾動的小圖片,也是一種廣告形式,需要的朋友可以收藏下
    2015-08-08
  • layer設(shè)置maxWidth及maxHeight解決方案

    layer設(shè)置maxWidth及maxHeight解決方案

    這篇文章主要介紹了layer設(shè)置maxWidth及maxHeight解決方案,非常不錯,具有一定的參考借鑒價值 ,需要的朋友可以參考下
    2019-07-07
  • js實現(xiàn)上傳圖片并顯示圖片名稱

    js實現(xiàn)上傳圖片并顯示圖片名稱

    這篇文章主要為大家詳細(xì)介紹了js實現(xiàn)上傳圖片并顯示圖片名稱,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • JS實現(xiàn)在狀態(tài)欄顯示打字效果完整實例

    JS實現(xiàn)在狀態(tài)欄顯示打字效果完整實例

    這篇文章主要介紹了JS實現(xiàn)在狀態(tài)欄顯示打字效果的方法,涉及JavaScript中字符遍歷結(jié)合時間函數(shù)對狀態(tài)欄顯示進(jìn)行操作的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-11-11
  • JS實現(xiàn)的Unicode編碼轉(zhuǎn)換操作示例

    JS實現(xiàn)的Unicode編碼轉(zhuǎn)換操作示例

    這篇文章主要介紹了JS實現(xiàn)的Unicode編碼轉(zhuǎn)換操作,結(jié)合完整實例形式分析了javascript實現(xiàn)Unicode編碼轉(zhuǎn)換的具體操作技巧,需要的朋友可以參考下
    2017-04-04
  • javascript拖曳互換div的位置實現(xiàn)示例

    javascript拖曳互換div的位置實現(xiàn)示例

    一個div拖動互換位置的demo,還有很大優(yōu)化的空間,利用dom元素的dragstart/ondragover/ondrop事件完成,感興趣的可以了解一下
    2021-06-06

最新評論

和顺县| 扶沟县| 青田县| 离岛区| 阳城县| 交城县| 武威市| 金寨县| 紫阳县| 吉安市| 新河县| 绥滨县| 始兴县| SHOW| 纳雍县| 射阳县| 吉首市| 崇义县| 双桥区| 安平县| 内江市| 普宁市| 大兴区| 道真| 石台县| 谷城县| 安陆市| 宁德市| 莒南县| 若尔盖县| 巴彦淖尔市| 资溪县| 涟水县| 思南县| 铁岭市| 平谷区| 景谷| 云梦县| 常山县| 吉木乃县| 手机|