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

JavaScript Promise與事件循環(huán)的深入理解

 更新時間:2026年02月24日 10:11:54   作者:鄭在努力中  
事件循環(huán)是JavaScript在單線程環(huán)境中實現(xiàn)并發(fā)的核心機(jī)制,它協(xié)調(diào)調(diào)用棧、任務(wù)隊列與微任務(wù)隊列,保證異步代碼以可預(yù)測的順序執(zhí)行,這篇文章主要介紹了JavaScript Promise與事件循環(huán)的相關(guān)資料,需要的朋友可以參考下

Promise

一、Promise 是什么?(定義)

官方說法:Promise 是一個用于表示異步操作最終結(jié)果的對象。

人話版:Promise 就是一個“承諾”:現(xiàn)在結(jié)果可能還沒出來,但將來一定會給你一個結(jié)果(成功 or 失?。?。

比如:請求接口(不知道什么時候返回)、讀取文件、定時任務(wù)、圖片上傳等

這些都需要 Promise。

二、為什么需要 Promise?

在 Promise 出現(xiàn)前,我們用的是 回調(diào)函數(shù)

ajax(url, success => {
  ajax(url2, success2 => {
    ajax(url3, success3 => {
      ...
    });
  });
});

這叫:回調(diào)地獄(Callback Hell)難讀、難維護(hù)、難錯誤處理

Promise 的目標(biāo):讓異步代碼寫得像同步一樣清晰。

三、Promise 的三種狀態(tài)

Promise 永遠(yuǎn)處于以下三種狀態(tài)之一:

狀態(tài)

含義

pending

進(jìn)行中

fulfilled

成功

rejected

失敗

特點:

  • 狀態(tài)一旦改變就 不可逆
  • 只能從 pending → fulfilled 或 pending → rejected

四、Promise 基本用法

1. 創(chuàng)建 Promise

使用 new Promise 來包裝異步邏輯。它接收一個函數(shù),這個函數(shù)有兩個參數(shù):resolve(成功時調(diào)用)和 reject(失敗時調(diào)用)。

const p = new Promise((resolve, reject) => {
  // 異步操作
  setTimeout(() => {
    resolve('成功結(jié)果');
    // reject('失敗原因');
  }, 1000);
});

參數(shù)說明:

  • resolve(value) → 成功
  • reject(error) → 失敗

2. 使用 Promise:then / catch

p.then(result => {
  console.log('成功:', result);
}).catch(error => {
  console.log('失敗:', error);
});

五、Promise 執(zhí)行流程(非常重要)

new Promise((resolve, reject) => {
  resolve(100);
})
.then(res => {
  return res + 1;
})
.then(res => {
  console.log(res); // 101
});

流程是:

  • Promise resolve(100)
  • 第一個 then 接收到 100
  • return res + 1 → 返回一個新的 Promise
  • 第二個 then 接收到 101

注意: then 是可以鏈?zhǔn)秸{(diào)用的

六、常用實例方法很常用

1. then

處理成功結(jié)果:

promise.then(res =>{})

2. catch

捕獲錯誤:

promise.catch(err => {})

等價于:

promise.then(null, err => {})

3. finally

無論成功失敗都會執(zhí)行:

promise.finally(() => {
  console.log('請求結(jié)束,關(guān)閉 loading');
});

七、常用靜態(tài)方法

這些是掛在 Promise 類上的方法:

1、Promise.resolve(value)

作用:快速返回一個 成功態(tài) Promise。

行為規(guī)則

Promise.resolve(普通值)      // fulfilled,值就是這個值
Promise.resolve(Promise對象) // 直接返回這個 Promise
Promise.resolve(thenable對象) // 會執(zhí)行 then

示例 1:包裝同步值為異步

Promise.resolve(10).then(v => {
  console.log(v); // 10
});

示例 2:統(tǒng)一函數(shù)返回 Promise

function getData() {
  if (cache) {
    return Promise.resolve(cache);
  }
  return fetch('/api').then(r => r.json());
}

常用于:讓函數(shù)無論同步/異步都返回 Promise

2、Promise.reject(reason)

作用:返回一個 失敗態(tài) Promise

Promise.reject('error').catch(err => {
  console.log(err); // error
});

實際場景:參數(shù)校驗失敗時直接中斷:

function submit(data) {
  if (!data.username) {
    return Promise.reject('用戶名不能為空');
  }
  return fetch('/submit');
}

3、Promise.all(promises)

核心規(guī)則:全部成功 → 成功||任何一個失敗 → 直接失敗

示例

const p1 = Promise.resolve(1);
const p2 = Promise.resolve(2);
const p3 = Promise.resolve(3);

Promise.all([p1, p2, p3])
  .then(res => {
    console.log(res); // [1, 2, 3]
  });

如果有一個失?。?/p>

const p1 = Promise.resolve(1);
const p2 = Promise.reject('錯了');
const p3 = Promise.resolve(3);

Promise.all([p1, p2, p3])
  .catch(err => {
    console.log(err); // "錯了"
  });

常見真實業(yè)務(wù),頁面初始化:

Promise.all([
  fetchUser(),
  fetchMenu(),
  fetchPermission()
]).then(([user, menu, permission]) => {
  renderPage();
});//數(shù)組的解構(gòu)賦值

4、Promise.race(promises)

規(guī)則:誰先完成(成功或失?。┚筒捎谜l的結(jié)果

示例:模擬超時控制

function timeout(ms) {
  return new Promise((_, reject) => {
    setTimeout(() => reject('請求超時'), ms);
  });
}

Promise.race([
  fetch('/api/data'),
  timeout(3000)
])
.then(res => console.log('成功'))
.catch(err => console.log(err));

實際意義:接口 3 秒內(nèi)沒返回就報超時

5、Promise.allSettled(promises)

規(guī)則:不管成功還是失敗,等所有 Promise 都結(jié)束

返回格式固定:

[
  { status: 'fulfilled', value: 成功值 },
  { status: 'rejected', reason: 失敗原因 }
]

示例

const p1 = Promise.resolve(100);
const p2 = Promise.reject('失敗了');

Promise.allSettled([p1, p2])
  .then(results => {
    console.log(results);
  });

真實場景:多個接口加載,允許部分失敗:

Promise.allSettled([
  loadBanner(),
  loadRecommend(),
  loadAds()
]).then(results => {
  const successData = results
    .filter(r => r.status === 'fulfilled')
    .map(r => r.value);

  render(successData);
});

6、Promise.any(promises)

規(guī)則:有一個成功就成功,全部失敗才失敗

示例

Promise.any([
  Promise.reject('A失敗'),
  Promise.reject('B失敗'),
  Promise.resolve('C成功')
]).then(res => {
  console.log(res); // C成功
});

如果全部失?。?/p>

Promise.any([
  Promise.reject('A'),
  Promise.reject('B')
]).catch(err => {
  console.log(err instanceof AggregateError); // true
  console.log(err.errors); // ['A', 'B']
});

真實場景:多 CDN 加載資源:

Promise.any([
  loadFromCDN1(),
  loadFromCDN2(),
  loadFromCDN3()
]).then(url => {
  console.log('成功加載:', url);
});

7、六個方法對比總結(jié)

方法

成功條件

失敗條件

典型用途

resolve

直接成功

不會失敗

包裝值

reject

不會成功

直接失敗

快速中斷

all

全部成功

任一失敗

多接口并發(fā)

race

第一個完成

第一個失敗

超時控制

allSettled

不關(guān)心

不關(guān)心

允許部分失敗

any

任一成功

全部失敗

多源容災(zāi)

八、async / await 與 Promise 的關(guān)系

async function getData() {
  const res = await fetch('/api');
  return res.json();
}

本質(zhì)上:async 函數(shù)永遠(yuǎn)返回 Promise,await 就是 then 的語法糖

等價于:

function getData() {
  return fetch('/api').then(res => res.json());
}

九、真實業(yè)務(wù)中的 Promise

1. 請求接口

axios.get('/api/user')
  .then(res => setUser(res.data))
  .catch(err => showError());

2. loading 狀態(tài)控制

setLoading(true);

fetchData()
  .finally(() => setLoading(false));

3. 順序執(zhí)行異步任務(wù)

async function run() {
  await step1();
  await step2();
  await step3();
}

事件循環(huán)

拆解成三個核心角色:調(diào)用棧(Call Stack)、任務(wù)隊列(Task Queue) 和 微任務(wù)隊列(Microtask Queue)。

1. 核心角色扮演

  • 調(diào)用棧 (Call Stack):這是主廚的工作臺。同步任務(wù)都在這里按“后進(jìn)先出”執(zhí)行。如果??樟?,說明主廚閑下來了。
  • 宿主環(huán)境 (Web APIs):這是廚房的助手(瀏覽器或 Node)。負(fù)責(zé)處理計時、網(wǎng)絡(luò)請求等耗時工作。
  • 任務(wù)隊列 (Task Queue):也叫宏任務(wù)(Macrotask)。這里存放著排隊等候的“大活”,比如 setTimeout 的回調(diào)、點擊事件處理函數(shù)。
  • 微任務(wù)隊列 (Microtask Queue):這是“插隊通道”。這里存放著優(yōu)先級極高的任務(wù),主要是 Promise 的回調(diào) (.then)。

2. 事件循環(huán)的執(zhí)行流程

可以把事件循環(huán)想象成一個永遠(yuǎn)在旋轉(zhuǎn)的轉(zhuǎn)盤,它的工作邏輯非常死板:

  • 執(zhí)行同步代碼:所有同步代碼都在調(diào)用棧里執(zhí)行,直到清空。
  • 清空微任務(wù) (Microtasks)
    • 主廚一看工作臺空了,第一件事不是去拉宏任務(wù),而是看微任務(wù)隊列。
    • 如果有微任務(wù),一口氣全部執(zhí)行完,直到微任務(wù)隊列清空。
  • 渲染頁面:瀏覽器會嘗試更新一次 UI(如果需要)。
  • 執(zhí)行一個宏任務(wù) (Macrotask)
    • 從宏任務(wù)隊列里只取出一個最前面的任務(wù),放到調(diào)用棧執(zhí)行。
  • 循環(huán)往復(fù):回到第 2 步,再次檢查微任務(wù)。

避坑點

  • 不要在微任務(wù)里遞歸:如果你在 Promise.then 里不停地產(chǎn)生新的 Promise,微任務(wù)隊列就永遠(yuǎn)清不空,頁面就會徹底卡死(因為宏任務(wù)和渲染都沒機(jī)會跑了)。
  • UI 渲染的時機(jī):UI 渲染通常發(fā)生在微任務(wù)清空之后、宏任務(wù)執(zhí)行之前。

3.例子

console.log('1. Script Start');

setTimeout(() => {
    console.log('2. setTimeout 1');
    Promise.resolve().then(() => {
        console.log('3. Promise in setTimeout');
    });
}, 0);

async function async1() {
    console.log('4. async1 Start');
    await async2();
    console.log('5. async1 End'); 
}

async function async2() {
    console.log('6. async2');
}

async1();

new Promise((resolve) => {
    console.log('7. Promise Constructor');
    resolve();
}).then(() => {
    console.log('8. Promise then');
});

setTimeout(() => {
    console.log('9. setTimeout 2');
}, 0);

console.log('10. Script End');

深度解析

  • 第一輪同步任務(wù)(主線執(zhí)行):
    • 打印 1. Script Start。
    • 遇到 setTimeout 1,丟進(jìn)宏任務(wù)。
    • 執(zhí)行 async1():打印 4. async1 Start。
    • 遇到 await async2():執(zhí)行 async2() 打印 6. async2注意!await 之后的代碼(打印 5)會被包裝成微任務(wù)
    • 執(zhí)行 Promise 構(gòu)造函數(shù):打印 7. Promise Constructor(構(gòu)造函數(shù)內(nèi)部是同步的?。?。.then 里的 8 丟進(jìn)微任務(wù)。
    • 遇到 setTimeout 2,丟進(jìn)宏任務(wù)。
    • 打印 10. Script End
    • 此時同步階段結(jié)束,順序:1, 4, 6, 7, 10。
  • 清空微任務(wù)(插隊階段):
    • 隊列里現(xiàn)在有:async1 End (5) 和 Promise then (8)。
    • 依次執(zhí)行,打印 5,再打印 8。
  • 執(zhí)行宏任務(wù)(下一輪循環(huán)):
    • 取出第一個 setTimeout:打印 2. setTimeout 1。
    • 關(guān)鍵點:它里面又產(chǎn)生了一個微任務(wù) 3
    • 根據(jù)事件循環(huán)規(guī)則,當(dāng)前宏任務(wù)執(zhí)行完后,必須清空新產(chǎn)生的微任務(wù),才能開始下一個宏任務(wù)。
    • 執(zhí)行微任務(wù),打印 3. Promise in setTimeout。
    • 取出第二個 setTimeout:打印 9. setTimeout 2

最終答案

1 -> 4 -> 6 -> 7 -> 10 -> 5 -> 8 -> 2 -> 3 -> 9

總結(jié) 

到此這篇關(guān)于JavaScript Promise與事件循環(huán)的深入理解的文章就介紹到這了,更多相關(guān)JS Promise與事件循環(huán)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

新密市| 宁乡县| 项城市| 上蔡县| 五河县| 明光市| 长宁县| 宜都市| 龙岩市| 黑河市| 达州市| 龙江县| 平度市| 丰原市| 石楼县| 浦江县| 平昌县| 溆浦县| 商水县| 通州市| 西宁市| 兰坪| 大石桥市| 河池市| 嘉祥县| 漳平市| 屏东县| 岗巴县| 成都市| 浦东新区| 丰城市| 额济纳旗| 邢台县| 峡江县| 丰原市| 亳州市| 观塘区| 商水县| 县级市| 梁平县| 班玛县|