-
实现 Promise.all
- 需要返回一个 promise
- 接收的参数是一个promise或者非promise值组成的数组,用Promise.resolve统一处理
- 当所有任务完成的时候resolve结果数组
- 当有一个reject的时候整个函数reject
- 边界情况:传入的为空数组
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
| const promiseAll = (jobs) => { return new Promise((resolve, reject) => { if (!Array.isArray(jobs)) { reject(new Error('传入的参数不是数组')) } if (jobs.length === 0) { resolve([]) } const result = [] let count = 0 for (let i = 0; i < jobs.length; i++) { Promise.resolve(jobs[i]) .then(res => { result[i] = res count++ if (count === jobs.length) { resolve(result) } }) .catch(e => { reject(e) }) } }) }
|
-
实现 Promise.race
- 需要返回一个 Promise
- 返回的 Promise 根据输入的数据的第一个敲定而敲定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const promiseRace = (jobs) => { return new Promise((resolve, reject) => { if (!Array.isArray(jobs)) { return reject(new Error("参数不是数组")); }
for (let job of jobs) { Promise.resolve(job) .then((res) => { resolve(res); }) .catch((e) => { reject(e); }); } }); };
|
-
实现 Promise.any
-
返回一个 promise 对象
-
当任意一个promise敲定时,返回的promise对象敲定
-
当可迭代参数里所有的都被拒绝时,返回的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
| const promiseAny = (jobs) => { return new Promise((resolve, reject) => { if (!Array.isArray(jobs)) { return reject(new Error("参数不是数组")); }
if (jobs.length === 0) { return reject(new Error("All promises were rejected")); }
let reasons = [] let count = 0 for (let i = 0; i < jobs.length; i++) { Promise.resolve(jobs[i]) .then(res => { resolve(res) }) .catch(e => { reasons[i] = e count++ if (count === jobs.length) { reject(reasons) } }) } }); };
|
-
实现 Promise.allSettled
-
Promise.allSettled 总会返回一个兑现的 promise
-
当入参都敲定(兑现或者拒绝)时,allSettled 返回的 promise 兑现
-
返回值是一个{ status: ‘fufilled’ | ‘rejected’, reason?, value? }
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
| function promiseAllSettled(jobs) { return new Promise((resolve, reject) => { if (!Array.isArray(jobs)) { return reject(new Error("参数不是数组")); }
if (jobs.length === 0) { return resolve([]); }
const result = []; let count = 0;
for (let i = 0; i < jobs.length; i++) { Promise.resolve(jobs[i]) .then((res) => { result[i] = { status: 'fulfilled', value: res }; count++; if (count === jobs.length) { resolve(result); } }) .catch((e) => { result[i] = { status: 'rejected', reason: e }; count++; if (count === jobs.length) { resolve(result); } }); } }); }
|
- 实现红绿灯机制:初始化绿灯,过4s后变成黄灯,过1s后变成红灯,过5s后变成绿灯,以此循环
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
| const states = [ { color: 'green', duration: 4 }, { color: 'yellow', duration: 1 }, { color: 'red', duration: 5 }, ]
const sleep = (duration) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve() }, duration * 1000) }) }
const trafficLight = async () => { while(true) { for (const state of states) { const { color, duration } = state console.log(color) await sleep(duration) } } }
trafficLight()
const startLight = () => { let chian = Promise.resolve() const runCircle = () => { states.forEach(state => { chain = chain.then(() => changeTo(state)) }) chain.then(runCircle) } } startLight()
|
- 异步任务 compose 函数
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
| const task1 = (pre) => new Promise((resolve, reject) => { setTimeout(() => { resolve(pre * 3) }, 1000) })
const task2 = (pre) => new Promise((resolve, reject) => { setTimeout(() => { resolve(pre + 4) }, 1000) })
const task3 = (pre) => new Promise((resolve, reject) => { setTimeout(() => { resolve(pre + 6) }, 1000) })
const compose = (queue = [], initialValue) => { const initial = Promise.resolve(initialValue) return queue.reduce((prePromise, currTask) => { return prePromise.then(currTask) }, initial) }
compose([task1, task2, task3], 2).then((res) => { console.log(res) })
|
- 不定参数柯里化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| const sum = (...args) => { return args.reduce((total, curr) => { return total + curr }, 0) }
const curry = (fn) => { let totalArgs = [] const curried = (...args) => { if (args.length === 0) { const result = fn.apply(null, totalArgs) totalArgs = [] return result } else { totalArgs.push(...args) return curried } } return curried } const curriedSum = curry(sum)
console.log(curriedSum(1)(2)(3)(4)())
|
- 防抖 / 节流
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
| const debounce = (fn, delay) => { let timer = null return function(...args) { const context = this if (timer) { clearTimeout(timer) } timer = setTimeout(() => { fn.apply(context, args) }, delay) } }
const throttle = (fn, frequent) => { let timer = null return function(...args) { const context = this if (timer) { return } timer = setTimeout(() => { fn.apply(context, args) timer = null }, frequent) } }
const throttle_immediate = (fn, delay) => { let lastTime = 0 return function(...args) { const context = this const currentTime = Date.now() if (Date.now - lastTime > delay) { fn.apply(context, args) lastTime = currentTime } } }
|
感谢您的支持 | Thank you for supporting
手撕代码
http://example.com/2025/10/17/8CodeByHand/