JSPromise 延展
BreezliPromise
什么是promise
作为异步函数,有四种状态
Pending 进行中(Pending) 用 new Promise()
创建对象
Fulfilled 成功(Resolved) 用 .then()
处理成功的结果
Rejected 失败 (Rejected) 用 .catch()
处理失败
Finally 结束 () 用 .finally()
结束
怎么用
异步函数
1 2 3 4 5 6 7 8 9 10 11
| const step_1 = new Promise((resolve, reject) => { setTimeout(() => resolve("奶茶"), 1000); });
const step_2 = (tea) => new Promise((resolve, reject) => { setTimeout(() => resolve(tea + "+珍珠"), 1000); });
const step_3 = (tea) => new Promise((resolve, reject) => { setTimeout(() => resolve(tea + "+奶盖"), 1000); });
|
链式调用
1 2 3 4 5 6 7 8 9 10 11 12
| step_1 .then(tea => step_2(tea)) .then(tea => step_3(tea)) .then(tea => { console.log("最终奶茶:", tea); }) .catch(error => { console.log("失败:", error); }) .finally(() => { console.log("结束并清理"); });
|
普通函数的回调地狱
每次回调都要判断error
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| step_1((error, tea) => { if (error) { console.log("失败:", error); } else { step_1(tea, (error, tea) => { if (error) { console.log("失败:", error); } else { step_1(tea, (error, tea) => { if (error) { console.log("失败:", error); } else { console.log("最终奶茶:", tea); } }); } }); } });
|
使用场景
网络请求
fetch返回一个promise对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function fetchData(url) { const headers = { "Content-Type": "application/json", ...options.headers, }; return fetch(url) .then(response => response.json()) .catch(error => { throw error; }); }
fetchData("https://api.example.com/data1") .then(data => console.log("数据加载成功:", data)) .catch(error => console.error("数据加载失败:", error)); fetchData("https://api.example.com/data2") .then(data => console.log("数据加载成功:", data)) .catch(error => console.error("数据加载失败:", error));
|
统一错误处理
回调函数中需要手动检查每个步骤的错误。
1 2 3 4 5 6 7 8 9 10 11
| new Promise((resolve, reject) => { setTimeout(() => { if (Math.random() > 0.5) { resolve("成功"); } else { reject("失败"); } }, 1000); }) .then(result => console.log(result)) .catch(error => console.error("捕获错误:", error));
|
状态管理
异步操作有三种状态:pending
(进行中)、fulfilled
(已完成)、rejected
(已失败)
1 2 3 4 5 6
| const promise = new Promise((resolve, reject) => { setTimeout(() => resolve("完成"), 1000); });
console.log(promise); setTimeout(() => console.log(promise), 1500);
|
链式调用
1 2 3 4 5
| step1() .then(result1 => step2(result1)) .then(result2 => step3(result2)) .then(finalResult => console.log(finalResult)) .catch(error => console.error(error));
|
手写promise()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
| class MyPromise { constructor(executor) { this.state = 'pending'; this.value = undefined; this.reason = undefined; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = [];
const resolve = (value) => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onFulfilledCallbacks.forEach(fn => fn()); } };
const reject = (reason) => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectedCallbacks.forEach(fn => fn()); } };
try { executor(resolve, reject); } catch (error) { reject(error); } }
then(onFulfilled, onRejected) { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
let promise2 = new MyPromise((resolve, reject) => { if (this.state === 'fulfilled') { setTimeout(() => { try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); }
if (this.state === 'rejected') { setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); }
if (this.state === 'pending') { this.onFulfilledCallbacks.push(() => { setTimeout(() => { try { let x = onFulfilled(this.value); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); });
this.onRejectedCallbacks.push(() => { setTimeout(() => { try { let x = onRejected(this.reason); resolvePromise(promise2, x, resolve, reject); } catch (error) { reject(error); } }, 0); }); } });
return promise2; }
catch(onRejected) { return this.then(null, onRejected); } }
function resolvePromise(promise2, x, resolve, reject) { if (promise2 === x) { return reject(new TypeError('Chaining cycle detected for promise')); }
let called;
if (x !== null && (typeof x === 'object' || typeof x === 'function')) { try { let then = x.then; if (typeof then === 'function') { then.call(x, y => { if (called) return; called = true; resolvePromise(promise2, y, resolve, reject); }, err => { if (called) return; called = true; reject(err); }); } else { resolve(x); } } catch (error) { if (called) return; called = true; reject(error); } } else { resolve(x); } }
|
什么是promise.all()
等待所有兑现(或第一个拒绝)的结果
怎么用
例子1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const step_1 = new Promise((resolve, reject) => { setTimeout(() => resolve("奶茶"), 1000); });
const step_2 = (tea) => new Promise((resolve, reject) => { setTimeout(() => resolve(tea + "+珍珠"), 1000); });
const step_3 = (tea) => new Promise((resolve, reject) => { setTimeout(() => resolve(tea + "+奶盖"), 1000); });
const step_4 = new Promise((resolve, reject) => { setTimeout(() => resolve("最终收拾"), 1000); });
|
1 2 3
| Promise.all([step_1, step_4]).then((allstep) => { console.log(allstep); });
|
例子2
1 2 3 4 5 6 7 8 9 10 11 12
| step_1 .then(tea => { return Promise.all([ Promise.resolve(tea), step_2(tea), step_3(tea), step_4 ]); }) .then(results => { console.log(results); });
|
1
| ["奶茶", "奶茶+珍珠", "奶茶+奶盖", "最终收拾"]
|
例子3
1 2 3 4 5 6 7 8 9 10 11
| const promises = [];
for (let i = 0; i < 10; i++) { promises.push(new Promise((resolve) => { setTimeout(() => resolve(`Promise ${i} 完成`), 1000); })); }
Promise.all(promises).then(results => { console.log(results); });
|
1 2 3 4 5 6 7 8 9 10 11 12
| [ "Promise 0 完成", "Promise 1 完成", "Promise 2 完成", "Promise 3 完成", "Promise 4 完成", "Promise 5 完成", "Promise 6 完成", "Promise 7 完成", "Promise 8 完成", "Promise 9 完成" ]
|
使用场景
常用于数据聚合、资源加载、并发任务等场景
并行网络请求
1 2 3 4 5 6 7 8 9
| const request1 = fetch("https://api.example.com/data1").then(res => res.json()); const request2 = fetch("https://api.example.com/data2").then(res => res.json());
Promise.all([request1, request2]) .then(([data1, data2]) => { console.log("请求1结果:", data1); console.log("请求2结果:", data2); }) .catch(error => console.error("请求失败:", error));
|
数据聚合
Promise.all
自动收集所有结果为一个数组,方便后续处理。
1 2 3 4 5 6 7 8 9
| const getUser = () => fetch("/user").then(res => res.json()); const getOrders = () => fetch("/orders").then(res => res.json());
Promise.all([getUser(), getOrders()]) .then(([user, orders]) => { console.log("用户信息:", user); console.log("订单列表:", orders); }) .catch(error => console.error("数据加载失败:", error));
|
快速失败
1 2 3 4 5 6 7
| const task1 = new Promise(resolve => setTimeout(() => resolve(1), 1000)); const task2 = new Promise((_, reject) => setTimeout(() => reject("出错了"), 500)); const task3 = new Promise(resolve => setTimeout(() => resolve(3), 1000));
Promise.all([task1, task2, task3]) .then(results => console.log("所有任务完成:", results)) .catch(error => console.error("任务失败:", error));
|
统一处理多个异步任务
避免多次调用 .then()
或手动合并结果。
1 2 3 4 5 6 7 8 9 10
| const tasks = [ new Promise(resolve => setTimeout(() => resolve("任务1完成"), 1000)), new Promise(resolve => setTimeout(() => resolve("任务2完成"), 1000)), new Promise(resolve => setTimeout(() => resolve("任务3完成"), 1000)) ];
Promise.all(tasks) .then(results => console.log("所有任务结果:", results)) .catch(error => console.error("任务失败:", error));
|
手写promise.all()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| function myPromiseAll(promises) { if (Array.isArray(promises)) { return new Promise((resolve, reject) => { let count = 0 const results = []
promises.forEach((promise, index) => { Promise.resolve(promise) .then((value) => { results[index] = value count ++ if (count === promises.length) { resolve(results) } }) .catch(reject) }) }) } else { return Promise.reject(new TypeError('传入的参数不是数组')) } }
|
1 2 3 4 5 6 7
| myPromiseAll([ new Promise((resolve) => setTimeout(() => resolve(1), 3000)), new Promise((resolve) => setTimeout(() => resolve(2), 2000)), new Promise((resolve) => setTimeout(() => resolve(3), 1000)), ]) .then(console.log) .catch(console.error)
|