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

JavaScript?Promise錯(cuò)誤處理與最佳實(shí)踐

 更新時(shí)間:2025年09月23日 14:52:35   作者:風(fēng)茫  
Promise是ES6異步編程解決方案,解決回調(diào)地獄問(wèn)題,支持鏈?zhǔn)秸{(diào)用、統(tǒng)一錯(cuò)誤處理,是現(xiàn)代JavaScript異步處理的基石,本文給大家介紹JavaScript Promise錯(cuò)誤處理與最佳實(shí)踐,感興趣的朋友一起看看吧

一句話概括
Promise 是 ES6 引入的異步編程解決方案,用于表示一個(gè)異步操作的最終完成或失敗,以及其返回的值。它解決了“回調(diào)地獄”(Callback Hell)問(wèn)題,使異步代碼更清晰、可讀、可維護(hù)。

一、為什么需要Promise?(歷史背景)

Promise 出現(xiàn)之前,JavaScript 主要通過(guò) 回調(diào)函數(shù)(Callback) 處理異步操作:

// 回調(diào)地獄(Callback Hell)
doTask1((err, result1) => {
  if (err) return handleError(err);
  doTask2(result1, (err, result2) => {
    if (err) return handleError(err);
    doTask3(result2, (err, result3) => {
      if (err) return handleError(err);
      console.log('完成:', result3);
    });
  });
});

回調(diào)函數(shù)的痛點(diǎn):

  • 嵌套層級(jí)深,難以閱讀
  • 錯(cuò)誤處理重復(fù)
  • 無(wú)法 returnthrow
  • 控制流復(fù)雜(并行、串行、競(jìng)態(tài)等)

Promise 的出現(xiàn)就是為了解決這些問(wèn)題。

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

Promise 對(duì)象有且僅有三種狀態(tài),一旦改變不可逆

狀態(tài)說(shuō)明
pending初始狀態(tài),進(jìn)行中
fulfilled成功狀態(tài),操作成功完成
rejected失敗狀態(tài),操作失敗
const promise = new Promise((resolve, reject) => {
  // 初始狀態(tài):pending
  if (success) {
    resolve(value);  // → fulfilled
  } else {
    reject(error);   // → rejected
  }
});

三、Promise構(gòu)造函數(shù)

new Promise(executor)
  • executor 是一個(gè)函數(shù),格式:(resolve, reject) => {}
  • resolve(value):將 Promise 狀態(tài)變?yōu)?fulfilled
  • reject(error):將 Promise 狀態(tài)變?yōu)?rejected
  • executor 會(huì)立即執(zhí)行
const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    Math.random() > 0.5 ? resolve('成功') : reject('失敗');
  }, 1000);
});

resolve不同值的區(qū)別

  1. 普通值或者對(duì)象,那么這個(gè)值會(huì)作為then回調(diào)的參數(shù)
  2. 另外一個(gè)Promise對(duì)象,那么這個(gè)新Promise會(huì)決定原來(lái)Promise的狀態(tài)
  3. thenable對(duì)象:這對(duì)象中有實(shí)現(xiàn)then方法,那么就會(huì)執(zhí)行該then方法,并且根據(jù)then方法的結(jié)果來(lái)決定Promise的狀態(tài)
const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1);
  }, 3000);
});
const promise = new Promise((resolve, reject) => {
  // 1. 普通值
  // resolve(1);
  // resolve([
  //   {
  //     name: "風(fēng)茫",
  //     age: 18,
  //   },
  //   {
  //     name: "fengmang",
  //     age: 30,
  //   },
  // ]);
  // 2. resolve(promise)
  // 如果resolve的值為Promise對(duì)象,那么當(dāng)前的Promise的狀態(tài)由傳入的promise來(lái)決定
  // resolve(p);
  // 3. resolve(thenable對(duì)象)
  // thenable對(duì)象: 對(duì)象有then方法,那么就會(huì)執(zhí)行then方法,并且根據(jù)then方法的結(jié)果來(lái)決定Promise的狀態(tài)
  resolve({
    name: "風(fēng)茫",
    then: function (resolve, reject) {
      Math.random() > 0.5 ? resolve(100) : reject("失敗");
    },
  });
});
promise
  .then((res) => {
    console.log("res :>> ", res);
  })
  .catch((err) => {
    console.log(err);
  });

四、Promise的核心方法

1..then(onFulfilled, onRejected)

注冊(cè)成功和失敗的回調(diào)。

p.then(
  (value) => { console.log(value); },      // fulfilled
  (error) => { console.error(error); }     // rejected
);

鏈?zhǔn)秸{(diào)用的關(guān)鍵:.then() 返回一個(gè)新的 Promise

then方法返回值

const promise = new Promise((resolve, reject) => {
  resolve("aaa");
});
const p2 = promise
  .then((res) => {
    console.log(res);
    return "bbb";
  })
  .then((res) => {
    console.log(res);
    return "ccc";
  });
p2.then((res) => {
  console.log(res);
}).catch((err) => {
  console.log(err);
});
/**
 * 輸出結(jié)果:
 * aaa
 * bbb
 * ccc 
 */

解釋

  1. Promise的 then方法是返回一個(gè)新的Promise,這個(gè)新Promise的決議是等到then方法傳入的回調(diào)函數(shù) 有返回值 時(shí)進(jìn)行決議
  2. 若是上一個(gè)then方法沒有使用return返回,則下一個(gè)then方法接收到的值是undefined
  3. 若是在then方法中return一個(gè)新的Promise,則下一個(gè)then方法需要等到新Promise決議之后才會(huì)執(zhí)行,將新的Promise決議結(jié)果返回給下一個(gè)then方法并執(zhí)行then方法

2..catch(onRejected)

捕獲錯(cuò)誤,相當(dāng)于 .then(null, onRejected)

p.catch(err => {
  console.error('出錯(cuò)了:', err);
});

推薦寫法:鏈?zhǔn)?.then().catch(),統(tǒng)一錯(cuò)誤處理

fetch('/api/data')
  .then(res => res.json())
  .then(data => console.log(data))
  .catch(err => console.error('請(qǐng)求失敗:', err));

3..finally(onFinally)

無(wú)論成功或失敗都會(huì)執(zhí)行,常用于清理資源。

p.finally(() => {
  console.log('請(qǐng)求完成,關(guān)閉 loading...');
});

不接收參數(shù),不改變結(jié)果,常用于加載狀態(tài)、資源釋放。

五、Promise靜態(tài)方法

1.Promise.resolve(value)

作用:返回一個(gè) fulfilled 的 Promise。

Promise.resolve(42).then(x => console.log(x)); // 42

等價(jià)于:

new Promise(resolve => resolve(42));

使用場(chǎng)景

  • 將值包裝為Promise:如果你有一個(gè)立即可用的值,但是你希望以 Promise 的形式來(lái)處理它(比如為了保持接口的一致性),你可以使用 Promise.resolve() 來(lái)將這個(gè)值包裝成一個(gè)已解決的 Promise。
let promise = Promise.resolve(42);
promise.then(function(value) {
 console.log(value); // 輸出: 42
});
  • 處理未知的返回值:當(dāng)你不確定某個(gè)函數(shù)會(huì)返回一個(gè)普通值還是一個(gè) Promise,但你希望統(tǒng)一用 then 方法來(lái)處理時(shí),可以使用 Promise.resolve() 來(lái)包裹該返回值。
function maybeAsync() {
  if (/* some condition */) {
    return new Promise(/* ... */);
  } else {
    return 'immediate value';
  }
}
Promise.resolve(maybeAsync()).then(function(result) {
  console.log(result);
});
  • 模擬異步行為:有時(shí)候,即使數(shù)據(jù)已經(jīng)準(zhǔn)備好了,你也可能想要通過(guò) Promise.resolve() 來(lái)“延遲”執(zhí)行某些代碼,以便于和其他異步操作保持一致的流程控制。
Promise.resolve().then(() => {
  console.log('This runs after the current call stack is cleared.');
});
  • Promise 鏈條的開始:在構(gòu)建一個(gè)由多個(gè)步驟組成的 Promise 鏈時(shí),如果沒有初始的 Promise 可供鏈?zhǔn)秸{(diào)用 .then().catch() 方法,可以使用 Promise.resolve() 作為起點(diǎn)。
 Promise.resolve()
     .then(() => console.log('First step'))
     .then(() => console.log('Second step'));

2.Promise.reject(reason)

返回一個(gè) rejected 的 Promise。

Promise.reject('出錯(cuò)了').catch(err => console.log(err));

3.Promise.all(iterable)

作用:接收一個(gè)可迭代對(duì)象(通常是數(shù)組),其中每個(gè)元素都是一個(gè) Promise,并發(fā)執(zhí)行多個(gè) Promise,返回一個(gè)新的Promise。全部成功才成功,任一失敗則整體失敗。

const p1 = Promise.resolve('A');
const p2 = Promise.resolve('B');
const p3 = Promise.reject('C');
Promise.all([p1, p2]).then(results => {
  console.log(results); // ['A', 'B']
});
Promise.all([p1, p2, p3]).catch(err => {
  console.log(err); // 'C'
});

適用于“所有請(qǐng)求都必須成功”的場(chǎng)景(如批量上傳)。

4.Promise.race(iterable)

返回第一個(gè)完成的 Promise(無(wú)論是成功還是失?。?。

const slow = new Promise(r => setTimeout(() => r('慢'), 2000));
const fast = new Promise(r => setTimeout(() => r('快'), 500));
Promise.race([slow, fast]).then(result => {
  console.log(result); // '快'
});

適用于“超時(shí)控制”:

function timeout(promise, ms) {
  const timeout = new Promise((_, reject) =>
    setTimeout(() => reject(new Error('超時(shí)')), ms)
  );
  return Promise.race([promise, timeout]);
}

5.Promise.allSettled(iterable)

等待所有 Promise 結(jié)束,無(wú)論成功或失敗,返回結(jié)果數(shù)組。

Promise.allSettled([p1, p2, p3]).then(results => {
  results.forEach((result, i) => {
    if (result.status === 'fulfilled') {
      console.log(`p${i+1} 成功:`, result.value);
    } else {
      console.log(`p${i+1} 失敗:`, result.reason);
    }
  });
});

適用于“不關(guān)心成敗,只想知道所有結(jié)果”的場(chǎng)景。

6.Promise.any(iterable)

返回第一個(gè)成功的 Promise;如果全部失敗,則拋出 AggregateError。

const fail1 = Promise.reject('錯(cuò)誤1');
const fail2 = Promise.reject('錯(cuò)誤2');
const success = Promise.resolve('成功');
Promise.any([fail1, fail2, success]).then(res => {
  console.log(res); // '成功'
});

適用于“只要有一個(gè)成功即可”的場(chǎng)景(如多源請(qǐng)求)。

六、Promise的執(zhí)行機(jī)制(微任務(wù))

Promise 的回調(diào)(.then.catch)屬于 微任務(wù)(microtask),在當(dāng)前宏任務(wù)結(jié)束后立即執(zhí)行。

console.log(1);
Promise.resolve().then(() => {
  console.log(2);
});
console.log(3);
// 輸出:1 → 3 → 2

微任務(wù)優(yōu)先級(jí)高于 setTimeout(宏任務(wù))

setTimeout(() => console.log(1), 0);
Promise.resolve().then(() => console.log(2));
console.log(3);
// 輸出:3 → 2 → 1

七、錯(cuò)誤處理最佳實(shí)踐

正確方式:使用.catch()

fetch('/api')
  .then(res => res.json())
  .then(data => { throw new Error('處理失敗'); })
  .catch(err => console.error(err)); // 能捕獲

錯(cuò)誤方式:在.then中不處理錯(cuò)誤

fetch('/api')
  .then(res => res.json(), err => console.error(err)) // 只能捕獲 fetch 失敗
  .then(data => { throw new Error('處理失敗'); })     // 這個(gè)錯(cuò)誤沒被捕獲!

建議:鏈?zhǔn)秸{(diào)用末尾加 .catch()

八、Promise的常見模式

1. 串行執(zhí)行(鏈?zhǔn)秸{(diào)用)

function asyncTask(name) {
  return Promise.resolve().then(() => {
    console.log(`執(zhí)行 ${name}`);
    return name;
  });
}
asyncTask('A')
  .then(() => asyncTask('B'))
  .then(() => asyncTask('C'));

2. 并行執(zhí)行

Promise.all([
  asyncTask('A'),
  asyncTask('B'),
  asyncTask('C')
]).then(results => console.log('全部完成'));

3. 重試機(jī)制

function retry(fn, times = 3) {
  return fn().catch(err => {
    if (times <= 1) throw err;
    return retry(fn, times - 1);
  });
}
retry(() => fetch('/api')).catch(console.error);

九、Promise的局限性

問(wèn)題說(shuō)明
無(wú)法取消一旦創(chuàng)建,無(wú)法中途取消
錯(cuò)誤冒泡未捕獲的錯(cuò)誤可能靜默失?。∟ode.js 會(huì)警告)
無(wú)法獲取進(jìn)度只有成功/失敗,不支持 onProgress
冗長(zhǎng)的 .then復(fù)雜邏輯仍難讀

解決方案:使用 async/await(ES2017)

async function getData() {
  try {
    const res = await fetch('/api');
    const data = await res.json();
    return data;
  } catch (err) {
    console.error('請(qǐng)求失敗:', err);
  }
}

十、總結(jié)

項(xiàng)目說(shuō)明
定位異步編程的標(biāo)準(zhǔn)化解決方案
核心價(jià)值解決回調(diào)地獄,提供鏈?zhǔn)秸{(diào)用和統(tǒng)一錯(cuò)誤處理
關(guān)鍵方法.then()、.catch()、.finally()
靜態(tài)方法allrace、allSettled、anyresolve、reject
執(zhí)行機(jī)制回調(diào)屬于微任務(wù),優(yōu)先級(jí)高
現(xiàn)代替代async/await(基于 Promise

最終結(jié)論
Promise 是現(xiàn)代 JavaScript 異步編程的基石。即使你使用 async/await,其底層仍是 Promise。掌握 Promise 是成為合格前端/Node.js 開發(fā)者的必經(jīng)之路

到此這篇關(guān)于JavaScript Promise錯(cuò)誤處理與最佳實(shí)踐的文章就介紹到這了,更多相關(guān)js promise內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

宁化县| 若羌县| 福建省| 大洼县| 遵义县| 措美县| 鸡东县| 富阳市| 威信县| 定襄县| 柞水县| 洪湖市| 长葛市| 云安县| 西林县| 忻城县| 类乌齐县| 凤凰县| 洛南县| 通道| 任丘市| 时尚| 台东市| 丰镇市| 静乐县| 墨玉县| 安新县| 乳山市| 加查县| 长沙县| 湖州市| 苗栗县| 龙川县| 西乌珠穆沁旗| 宜兴市| 洮南市| 桓仁| 马关县| 鸡西市| 晴隆县| 平潭县|