# Promises 和 Time

# 两个 Promise 对象相加

给定两个 promise 对象 promise1 和 promise2,返回一个新的 promise。promise1 和 promise2 都会被解析为一个数字。返回的 Promise 应该解析为这两个数字的和。

# 示例 1:

输入:
promise1 = new Promise(resolve => setTimeout(() => resolve(2), 20)),
promise2 = new Promise(resolve => setTimeout(() => resolve(5), 60))
输出:7
解释:两个输入的 Promise 分别解析为值 2 和 5。返回的 Promise 应该解析为 2 + 5 = 7。返回的 Promise 解析的时间不作为判断条件。

# 示例 2:

输入:
promise1 = new Promise(resolve => setTimeout(() => resolve(10), 50)),
promise2 = new Promise(resolve => setTimeout(() => resolve(-12), 30))
输出:-2
解释:两个输入的 Promise 分别解析为值 10 和 -12。返回的 Promise 应该解析为 10 + -12 = -2。

# 题解

# 方法一 使用 Promise.all

我们可以使用 Promise.all() 创建一个新的 Promise,该 Promise 在 promise1 和 promise2 都被解决时解决。

const addTwoPromises = async (premise1, premise2) => {
    try {
        const [res1, res2] = await Promise.all([premise1, premise2]);
        return res1 + res2;
    } catch (error) {
        throw error; // 重新抛出错误以保持将错误传播给调用者的行为
    }
};
addTwoPromises(
    new Promise((resolve) => setTimeout(() => resolve(2), 20)),
    new Promise((resolve) => setTimeout(() => resolve(5), 5000))
)
    .then((res) => {
        console.log("结果", res); //7
    })
    .catch((e) => {
        console.log(e);
    });

# 方法二 仅使用 await

addTwoPromises 函数被定义为一个异步函数,允许我们在其中使用 await 。这种方法的直观思想是等待 promise1 和 promise2 的解析,然后计算它们的已解析值,即我们可以直接在 Promise 上使用 await,然后返回和。

请注意:直接在 promise1 和 promise2 上使用 await 不如使用 Promise.all() 并行,因为一个接一个地等待 Promise 将导致总解析时间较长,与使用 Promise.all() 并行等待相比。

/**
 * @param {Promise} promise1
 * @param {Promise} promise2
 * @return {Promise}
 */
const addTwoPromises = async function (promise1, promise2) {
        try {
            return await promise1 + await promise2;
        } catch (error) {
            console.error(error);
            throw error; // 重新抛出错误以保持将错误传播给调用者的行为
        }
    };

# 睡眠函数

请你编写一个异步函数,它接收一个正整数参数 millis ,并休眠 millis 毫秒。要求此函数可以解析任何值。

# 示例 1:

输入:millis = 100
输出:100
解释:
在 100ms 后此异步函数执行完时返回一个 Promise 对象
let t = Date.now();
sleep(100).then(() => {
console.log(Date.now() - t); // 100
});

# 示例 2:

输入:millis = 200
输出:200
解释:在 200ms 后函数执行完时返回一个 Promise 对象

# 题解

# 方法 1:使用 Promises 和 setTimeout 的异步编程

  • 定义一个名为 sleep(millis) 的异步函数。此函数在解析之前将暂停执行 millis 毫秒。
  • 在该函数内部,构造一个新的 promise 对象。这个 promise 对象的 executor 函数是我们将合并延迟的地方。
  • 在 executor 函数中,使用 setTimeout 方法。setTimeout 是由主机环境(Web 浏览器、Node.js等)提供的方法。它在指定的延迟后执行提供的函数或代码段。
  • 将 setTimeout 的延迟设置为 millis 毫秒。延迟后执行的代码将是 promise 的 resolve 方法。
  • 当调用 resolve 方法时,它会将承诺标记为已实现,从而允许执行任何附加的 .then 处理程序。
async function sleep(millis) {
    return new Promise((resolve) => {
        setTimeout(resolve, millis);
    });
}

let t = Date.now();
sleep(100).then(() => {
    console.log(Date.now() - t); // 100
});

# 执行可取消的延迟函数

现给定一个函数 fn ,一个参数数组 args 和一个以毫秒为单位的超时时间 t ,返回一个取消函数 cancelFn 。

在经过 t 毫秒的延迟后,应该调用 fn 函数,并将 args 作为参数传递。除非 在 t 毫秒的延迟过程中,在 cancelT 毫秒时调用了 cancelFn。并且在这种情况下,fn 函数不应该被调用。

# 示例 1:

输入:fn = (x) => x * 5, args = [2], t = 20, cancelT = 50 输出:[{"time": 20, "returned": 10}] 解释: const cancel = cancellable((x) => x * 5, [2], 20); // fn(2) 在 t=20ms 时被调用 setTimeout(cancel, 50);

取消操作被安排在延迟了 cancelT(50毫秒)后进行,这发生在 fn(2) 在20毫秒时执行之后。

# 示例 2:

输入:fn = (x) => x2, args = [2], t = 100, cancelT = 50
输出:[]
解释:
const cancel = cancellable((x) => x
2, [2], 100); // fn(2) 没被调用
setTimeout(cancel, 50);

取消操作被安排在延迟了 cancelT(50毫秒)后进行,这发生在 fn(2) 在100毫秒时执行之前,导致 fn(2) 从未被调用。

# 示例 3:

输入:fn = (x1, x2) => x1 * x2, args = [2,4], t = 30, cancelTime = 100
输出:[{"time": 30, "returned": 8}]
解释:
const cancel = cancellable((x1, x2) => x1 * x2, [2,4], 30); // fn(2,4) 在 t=30ms 时被调用
setTimeout(cancel, 100);

取消操作被安排在延迟了 cancelT(100毫秒)后进行,这发生在 fn(2,4) 在30毫秒时执行之后。

# 题解

# 方法一

/**
 * 延迟函数
 * @param {function} fn 延迟执行的函数
 * @param {[]} arg 传递给fn的数据
 * @param {number} t 延迟时间
 * @return {function} 取消延时器方法
 */
const detail = (fn, arg, t) => {
        const timer = setTimeout(() => fn(...arg), t);
        return () => clearTimeout(timer);
    };
const clear = detail(
    (x) => {
        console.log("执行");
        return x + 5;
    },
    [2],
    100
);
setTimeout(clear, 500); //不执行
setTimeout(clear, 30); //执行

# 间隔取消

现给定一个函数 fn,一个参数数组 args 和一个时间间隔 t,返回一个取消函数 cancelFn。

函数 fn 应该立即使用 args 调用,并且在每个 t 毫秒内再次调用,直到调用 cancelFn。

# 示例 1:

输入:fn = (x) => x * 2, args = [4], t = 35, cancelT = 190
输出:
[ {"time": 0, "returned": 8},
{"time": 35, "returned": 8},
{"time": 70, "returned": 8},
{"time": 105, "returned": 8},
{"time": 140, "returned": 8},
{"time": 175, "returned": 8}
]
解释:

const result = []
const fn = (x) => x * 2
const args = [4], t = 35, cancelT = 190

const start = performance.now()

const log = (...argsArr) => {
    const diff = Math.floor(performance.now() - start)
    result.push({"time": diff, "returned": fn(...argsArr)})
}

const cancel = cancellable(log, [4], 35);
setTimeout(cancel, 190);

setTimeout(() => {
    console.log(result) // Output
}, cancelT + t + 15)

每隔 35ms,调用 fn(4)。
输入:fn =(x)=> x * 2,args = [4],t = 35,cancelT = 190
输出:[ {“time”:0,“returned”:8},{“time”:35,“returned”:8},{“time”:70,“returned”:8},{“time”:105,“returned”:8},{“time”:140,“returned”:8},{“time”:175,“returned”:8} ]
解释说明performance.now. argsArr)=> { const diff = Math.floor(performance.now()- start)result.push({“time”:diff,“returned”:fn(. argsArr)})} const cancel = cancellable(log,[4],35);
setcancel(cancel,190); setcancel(()=> { console.log(result)// Output },cancelT + t + 15)每隔35 ms,调用 fn(4).
直到 t=190ms,然后取消。
第一次调用 fn 是在 0ms。fn(4) 返回 8。
第二次调用 fn 是在 35ms。fn(4) 返回 8。
第三次调用 fn 是在 70ms。fn(4) 返回 8。
第四次调用 fn 是在 105ms。fn(4) 返回 8。
第五次调用 fn 是在 140ms。fn(4) 返回 8。
第六次调用 fn 是在 175ms。fn(4) 返回 8。
在 t=190ms 时取消

# 示例 2:

输入:fn = (x1, x2) => (x1 * x2), args = [2, 5], t = 30, cancelT = 165
输出:
[ {"time": 0, "returned": 10},
{"time": 30, "returned": 10},
{"time": 60, "returned": 10},
{"time": 90, "returned": 10},
{"time": 120, "returned": 10},
{"time": 150, "returned": 10}
]
解释:
const cancel = cancellable((x1, x2) => (x1 * x2), [2, 5], 30);
setTimeout(cancel, 165);

每隔 30ms,调用 fn(2, 5)。直到 t=165ms,然后取消。
第一次调用 fn 是在 0ms
第二次调用 fn 是在 30ms
第三次调用 fn 是在 60ms
第四次调用 fn 是在 90ms
第五次调用 fn 是在 120ms
第六次调用 fn 是在 150ms
在 165ms 取消

# 示例 3:

输入:fn = (x1, x2, x3) => (x1 + x2 + x3), args = [5, 1, 3], t = 50, cancelT = 180
输出:
[ {"time": 0, "returned": 9},
{"time": 50, "returned": 9},
{"time": 100, "returned": 9},
{"time": 150, "returned": 9}
] 解释:
const cancel = cancellable((x1, x2, x3) => (x1 + x2 + x3), [5, 1, 3], 50);
setTimeout(cancel, cancelT);

每隔 50ms,调用 fn(5, 1, 3)。直到 t=180ms,然后取消。
第一次调用 fn 是在 0ms
第二次调用 fn 是在 50ms
第三次调用 fn 是在 100ms
第四次调用 fn 是在 150ms
在 180ms 取消

# 题解

# 方法 1 使用 setInterval 和 clearInterval

要设置一个间隔计时器,我们使用 setInterval 函数。在下面的代码片段中,setInterval 将每隔 t 毫秒调用 () => fn(...args) 。值得注意的是,在设置间隔之前,setInterval 不会立即调用该函数,这就是为什么我们在设置间隔之前手动调用了 fn(...args)。

接下来,我们定义了一个名为 cancelFn 的函数,当它被调用时,会清除间隔。我们从主函数返回 cancelFn。值得一提的是,cancelFn 在我们的可取消函数首次定义时不会被调用。然而,每当可取消函数被调用时,它都会返回 cancelFn。然后可以在以后的某个时候调用 cancelFn 以清除间隔。

/**
 * 间隔取消函数
 * @param fun {Function} 函数
 * @param args {Array} 函数参数
 * @param time {Number} 间隔调用时间
 */
const detailFun = (fun, args, time) => {
        fun(...args);
        const timer = setInterval(() => fun(...args), time);
        return () => clearInterval(timer);
    };
const clearTimer = detailFun((x) => x * 2, [4], 1000);

# 方法 2:使用递归

我们可以设置一个定时间隔,其中函数将被重复执行。这将提供一种在需要时取消间隔执行的方式。简单来说,只要布尔标志未切换,每个函数都会不断调用自身(经过 t 毫秒,通过一个超时函数)。

算法:

当我们调用可取消函数时,首先使用给定的参数 (args) 执行提供的函数 (fn),即 fn(...args)。这确保了在启动间隔之前至少会调用一次函数。

接下来,我们定义了一个名为 startInterval 的内部函数。此函数通过使用 setTimeout 来等待指定的 t,然后再次执行函数(fn)。它重复这个过程,直到我们决定取消间隔,这将由我们在代码开始时声明的布尔变量 isCancelled 决定。

为了创建这种重复执行,startInterval 使用了一个巧妙的技巧。它在 setTimeout 回调函数内部递归调用自身。这意味着在每次执行函数后,通过再次调用 startInterval 来安排下一次执行。这会创建一种循环的行为,其中函数被执行,然后再次调用 startInterval 以安排下一次执行。

/**
 * @param {Function} fn
 * @param {Array} args
 * @param {number} t
 * @return {Function}
 */
var cancellable = function (fn, args, t) {
        let timerId = null;
        fn(...args);

        const startInterval = () => {
            timerId = setTimeout(() => {
                fn(...args);
                startInterval();
            }, t);
        };
        startInterval();

        const cancelInterval = () => {
            if (timerId !== null) {
                clearTimeout(timerId);
            }
        };

        return cancelInterval;
    };

# 有时间限制的 Promise 对象

请你编写一个函数,它接受一个异步函数 fn 和一个以毫秒为单位的时间 t。它应根据限时函数返回一个有 限时 效果的函数。函数 fn 接受提供给 限时 函数的参数。 限时 函数应遵循以下规则:

如果 fn 在 t 毫秒的时间限制内完成,限时 函数应返回结果。 如果 fn 的执行超过时间限制,限时 函数应拒绝并返回字符串 "Time Limit Exceeded" 。

# 示例 1:

输入:
fn = async (n) => { await new Promise(res => setTimeout(res, 100)); return n * n; }
inputs = [5]
t = 50
输出:{"rejected":"Time Limit Exceeded","time":50}
解释:
const limited = timeLimit(fn, t)
const start = performance.now()
let result;
try { const res = await limited(...inputs) result = {"resolved": res, "time": Math.floor(performance.now() - start)}; } catch (err) { result = {"rejected": err, "time": Math.floor(performance.now() - start)}; }
console.log(result) // 输出结果

提供的函数设置在 100ms 后执行完成,但是设置的超时时间为 50ms,所以在 t=50ms 时拒绝因为达到了超时时间。

输入:fn = alert c(n)=> { await new Promise(res => setReply(res,100)); return n * n; } inputs = [5] t = 50
输出:performance.now{“rejected”:“Time Limit Exceeded”,“time”:50} 解释:const limited = timeLimit(fn,t)const
start = www.example.com()let result; try { const res = await limited(. inputs)result =
{“resolved”:res,“time”:Math.floor(performance.now()- start)}; } catch(err){ result =
{“rejected”:err,“time”:Math.floor(performance.now()- start)}; } console.log(result)//抛出结果
In this paper,we discuss the relationship between the mechanism and the relationship between the mechanism.

# 示例 2:

输入:
fn = async (n) => {
await new Promise(res => setTimeout(res, 100));
return n * n;
}
inputs = [5]
t = 150
输出:{"resolved":25,"time":100}
解释:
在 t=100ms 时执行 5*5=25 ,没有达到超时时间。

# 示例 3:

输入:
fn = async (a, b) => {
await new Promise(res => setTimeout(res, 120));
return a + b;
}
inputs = [5,10]
t = 150
输出:{"resolved":15,"time":120}
解释:
在 t=120ms 时执行 5+10=15,没有达到超时时间。

# 示例 4:

输入:
fn = async () => {
throw "Error";
}
inputs = []
t = 1000
输出:{"rejected":"Error","time":0}
解释:
此函数始终丢出 Error

# 提示:

0 <= inputs.length <= 10
0 <= t <= 1000
fn 返回一个 Promise 对象

# 题解

# 方法 1:在新 Promise 内部调用函数

我们可以创建一个新的 Promise,它在传递的函数解析或拒绝时立即解析。这本质上是模拟了传递的函数,而不对其产生任何影响。要满足要求,我们只需要添加一个 setTimeout,它可以提前强制拒绝 Promise。

/**
 * 限时函数
 * @param {Promise} fun 执行的函数
 * @param {Number} time 限时时间
 */
const detailFun = (fun, time) => {
        return (...args) => {
            return new Promise((res, rej) => {
                setTimeout(() => {
                    rej("Time Limit Exceeded");
                }, time);
                fun(...args)
                    .then(res)
                    .catch(rej);
            });
        };
    };
const fun1 = detailFun(async (n) => {
    await new Promise((res) => setTimeout(res, 100));
    return n * n;
}, 200);
fun1(5)
    .then((res) => {
        console.log("结果", res);
    })
    .catch((e) => console.log(e));

# 方法 2:处理清除 Timeout

在上面的示例中,如果函数的 Promise 在时间限制到期之前完成,拒绝逻辑仍然会在将来的某个时候被不必要地触发。这不会对函数的外部行为产生任何影响,因为 Promise 只能解析或拒绝一次。拒绝已解析的 Promise 不会产生任何效果。

然而,想象一下如果时间限制设置得非常长。这些代码块将不得不在 JavaScript 事件循环最终执行它们之前在内存中存储很长时间。这可能被视为内存泄漏,而专业的实现应该避免这种情况。不过,这并不是这个问题的要求。

为了实现这一点,我们可以利用 setTimeout 返回的整数 ID,这实际上是对要执行的代码块的引用。然后,你可以使用内置的 clearTimeout(id) 来中止代码的执行。

我们还可以利用 Promise.finally 方法。传递给它的回调将在 Promise 解析或拒绝时执行。

var timeLimit = function (fn, t) {
    return async function (...args) {
        return new Promise((resolve, reject) => {
            const timeout = setTimeout(() => {
                reject("Time Limit Exceeded");
            }, t);
            fn(...args)
                .then(resolve)
                .catch(reject)
                .finally(() => clearTimeout(timeout));
        })
    }
};

# 方法 3:Promise Race

我们可以通过使用 Promise.race 函数来简化代码。它接受一个 Promise 数组并返回一个新的 Promise。返回的 Promise 将解析或拒绝其中一个 Promise 解析或拒绝的第一个值。

var timeLimit = function (fn, t) {
    return async function (...args) {
        const timeLimitPromise = new Promise((resolve, reject) => {
            setTimeout(() => reject("Time Limit Exceeded"), t)
        });
        const returnedPromise = fn(...args);
        return Promise.race([timeLimitPromise, returnedPromise]);
    }
};

# 方法 4:Async/Await + 清除 Timeout

我们可以修改方法 2 以使用 async/await 语法。你只能在异步函数内使用 await 关键字,因此我们必须将 async 关键字添加到传递给新 Promise 的回调中。现在回调返回一个 Promise,而不是 undefined。请注意,这是可以接受的,因为 Promise 构造函数不会查看回调返回的内容。不过,一个常见的错误是不恰当地将代码标记为异步。

var timeLimit = function (fn, t) {
    return async function (...args) {
        return new Promise(async (resolve, reject) => {
            const timeout = setTimeout(() => {
                reject("Time Limit Exceeded");
            }, t);

            try {
                const result = await fn(...args);
                resolve(result);
            } catch (err) {
                reject(err);
            }
            clearTimeout(timeout);
        });
    }
}

# 函数防抖

请你编写一个函数,接收参数为另一个函数和一个以毫秒为单位的时间 t ,并返回该函数的 函数防抖 后的结果。

函数防抖 方法是一个函数,它的执行被延迟了 t 毫秒,如果在这个时间窗口内再次调用它,它的执行将被取消。你编写的防抖函数也应该接收传递的参数。

例如,假设 t = 50ms ,函数分别在 30ms 、 60ms 和 100ms 时调用。前两个函数调用将被取消,第三个函数调用将在 150ms 执行。如果改为 t = 35ms ,则第一个调用将被取消,第二个调用将在 95ms 执行,第三个调用将在 135ms 执行。

# 示例 1:

输入:
t = 50
calls = [
{"t": 50, inputs: [1]},
{"t": 75, inputs: [2]}
]
输出:[{"t": 125, inputs: [2]}]
解释:
let start = Date.now();
function log(...inputs) {
console.log([Date.now() - start, inputs ])
}
const dlog = debounce(log, 50);
setTimeout(() => dlog(1), 50);
setTimeout(() => dlog(2), 75);

第一次调用被第二次调用取消,因为第二次调用发生在 100ms 之前
第二次调用延迟 50ms,在 125ms 执行。输入为 (2)。

# 示例 2:

输入:
t = 20
calls = [
{"t": 50, inputs: [1]},
{"t": 100, inputs: [2]}
]
输出:[{"t": 70, inputs: [1]}, {"t": 120, inputs: [2]}]
解释:
第一次调用延迟到 70ms。输入为 (1)。
第二次调用延迟到 120ms。输入为 (2)。

# 示例 3:

输入:
t = 150
calls = [
{"t": 50, inputs: [1, 2]},
{"t": 300, inputs: [3, 4]},
{"t": 300, inputs: [5, 6]}
] 输出:[{"t": 200, inputs: [1,2]}, {"t": 450, inputs: [5, 6]}]
解释:
第一次调用延迟了 150ms,运行时间为 200ms。输入为 (1, 2)。
第二次调用被第三次调用取消
第三次调用延迟了 150ms,运行时间为 450ms。输入为 (5, 6)。

# 提示:

0 <= t <= 1000
1 <= calls.length <= 10
0 <= calls[i].t <= 1000
0 <= calls[i].inputs.length <= 10

# 题解

/**
 * 防抖函数
 * @param {Function} fun 执行的函数
 * @param {number} num 防抖时间
 */
const debounce = (fun, num) => {
        let timer;
        return (...args) => {
            clearTimeout(timer);
            timer = setTimeout(() => fun(args), num);
        };
    };
const fun = debounce(() => console.log("执行", count), 50);
let count = 0;
const timer = setInterval(() => {
    if (count > 10) clearInterval(timer);
    fun();
    count++;
}, 40);

# 并行执行异步函数

给定一个异步函数数组 functions,返回一个新的 promise 对象 promise。数组中的每个函数都不接受参数并返回一个 promise。所有的 promise 都应该并行执行。

promise resolve 条件:

当所有从 functions 返回的 promise 都成功的并行解析时。promise 的解析值应该是一个按照它们在 functions 中的顺序排列的 promise 的解析值数组。promise 应该在数组中的所有异步函数并行执行完成时解析。 promise reject 条件:

当任何从 functions 返回的 promise 被拒绝时。promise 也会被拒绝,并返回第一个拒绝的原因。 请在不使用内置的 Promise.all 函数的情况下解决。

# 示例 1:

输入:functions = [
() => new Promise(resolve => setTimeout(() => resolve(5), 200))
]
输出:{"t": 200, "resolved": [5]}
解释:
promiseAll(functions).then(console.log); // [5]

单个函数在 200 毫秒后以值 5 成功解析。

# 示例 2:

输入:functions = [
() => new Promise(resolve => setTimeout(() => resolve(1), 200)),
() => new Promise((resolve, reject) => setTimeout(() => reject("Error"), 100))
]
输出:{"t": 100, "rejected": "Error"}
解释:由于其中一个 promise 被拒绝,返回的 promise 也在同一时间被拒绝并返回相同的错误。

# 示例 3:

输入:functions = [
() => new Promise(resolve => setTimeout(() => resolve(4), 50)),
() => new Promise(resolve => setTimeout(() => resolve(10), 150)),
() => new Promise(resolve => setTimeout(() => resolve(16), 100))
]
输出:{"t": 150, "resolved": [4, 10, 16]}
解释:所有的 promise 都成功执行。当最后一个 promise 被解析时,返回的 promise 也被解析了。

# 提示:

函数 functions 是一个返回 promise 的函数数组 1 <= functions.length <= 10

# 方法 1:模拟 Promise.all() 的行为

目标是复制 JavaScript 内置的 Promise.all() 方法的功能。具体来说,我们需要管理一组返回 Promise 的函数,并返回一个 Promise,该 Promise 解析为结果数组,保留原始数组的顺序。我们将自己处理 Promise 的解析,可以使用现代的 async/await 语法或经典的 then/catch 语法。 算法

  • 从 promiseAll 函数返回一个新 Promise。
  • 如果输入数组为空,立即用一个空数组解析它并返回。
  • 初始化一个数组 res 以保存结果,最初填充为 null。
  • 初始化一个 resolvedCount 变量,用于跟踪已解析的 Promise 数。
  • 迭代 Promise 返回函数的数组。对于每个返回 Promise 的函数:
  • 在 async/await 版本中,等待 Promise。在解析时,将结果放入 res 数组中的相应位置并增加 resolvedCount。如果引发错误,立即用错误拒绝 Promise。
  • 在 then/catch 版本中,附加一个 then 子句和一个 catch 子句。在解析时,then 子句将结果放入 res 数组中并增加 resolvedCount。catch 子句用错误拒绝 Promise。
  • 如果所有 Promise 都已解析(即 resolvedCount 等于函数数组的长度),则使用 res 数组解析 promiseAll() Promise。

async/await 版本和 then/catch 版本的主要区别在于语法和等待/处理 Promise 的方式,但总体方法保持不变。这两种实现都确保所有 Promise 同时开始(而不是按顺序),并且返回的 Promise 解析为它们的结果数组,保持原始顺序。

/**
 * 异步函数并行执行函数
 * @param {Promise[]} Promise数组
 */
const promiseAll = (promiseAll) => {
        return new Promise((res, rej) => {
            if (promiseAll.length === 0) res([]);
            const result = new Array(promiseAll.length).fill(null);
            let resoveCount = 0;
            promiseAll.map((item, index) =>
                item()
                    .then((itemSucc) => {
                        result[index] = itemSucc;
                        resoveCount++;
                        if (resoveCount === promiseAll.length) res(result);
                    })
                    .catch(rej)
            );
        });
    };
promiseAll([() => new Promise((resolve, rej) => setTimeout(() => rej(5), 200))])
    .then((res) => {
        console.log("结果", res);
    })
    .catch((e) => {
        console.log("错误", e);
    });


//async / await
var promiseAll = async function (functions) {
    return new Promise((resolve, reject) => {
        if (functions.length === []) {
            resolve([])
            return
        }

        const res = new Array(functions.length).fill(null)

        let resolvedCount = 0

        functions.forEach(async (el, idx) => {
            try {
                const subResult = await el()
                res[idx] = subResult
                resolvedCount++
                if (resolvedCount === functions.length) {
                    resolve(res)
                }
            } catch (err) {
                reject(err)
            }
        })
    })
};
上次更新: 11/8/2023, 5:29:52 PM