我的任务是模拟 Promise.last 方法,我返回一个最后解决的 Promise
export const PROMISE1 = new Promise<string>((resolve, reject) => {
setTimeout(() => resolve("First Promise Resolved"), 2000);
});
export const PROMISE2 = new Promise<string>((resolve, reject) => {
setTimeout(() => resolve("Second Promise Resolved"), 3000);
});
export const PROMISE3 = new Promise<string>((resolve, reject) => {
setTimeout(() => resolve("Third Promise Resolved"), 1000);
});
export const PROMISEARRAY = [PROMISE1, PROMISE2, PROMISE3];
export const isArrayEmpty = <T>(array: Promise<T>[]) => {
if (!array.length) {
throw new Error("Please type an array with at least one promise");
}
};
const promiseAllArr = <T>(arrayOfPromises: Promise<T>[]): Promise<T[]> => {
isArrayEmpty(arrayOfPromises);
const arr = [] as T[];
// return new Promise((resolve, reject) => {
// arrayOfPromises.forEach((element) => {
// element
// .then((value) => {
// arr.push(value);
// resolve(arr);
// })
// .catch((error) => reject(error));
// });
// });
return new Promise((resolve, reject) => {
for (let i = 0; i < arrayOfPromises.length; i++) {
arrayOfPromises[i].then((value) => {
arr.push(value);
resolve(arr);
});
}
});
const promiseLast = <T>(arrayOfPromises: Promise<T>[]): Promise<T> => {
return promiseAllArr(arrayOfPromises).then((data) => {
if (data.length) {
console.log(data.length);
return arrayOfPromises[arrayOfPromises.length - 1];
}
throw new Error("array error");
});
};
const promiseLastResult = promiseLast(PROMISEARRAY);
console.log(promiseLastResult);
setTimeout(() => {
promiseLastResult.then((data) => {
console.log(data);
});
}, 6000);
PromiseAll 模拟效果很好,但是当我尝试返回 PromiseLast 时,我得到了第一个已解决的承诺。如果是这样,为什么我会在 PromiseAll 中得到所有三个结果?
我已经尝试过 for 循环、forEach,但我不能使用 async/await -> 这将是我的下一个案例。
代码中的主要问题是您的
promiseAllArr()
函数调用在第一个解决的承诺上解决。因此,它永远不会等待其余的完成,当然也不会等待最后一个。因此,您尝试在最后一个承诺完成之前检查结果。
这是我将如何实现这一点。请注意,我允许
promiseLast()
的参数是可迭代的(就像 Promise.all()
一样),因此它不必是数组。我已经用普通的 Javascript 实现了这个,所以它会在代码片段中运行。
function promiseLast(promises) {
return new Promise((resolve, reject) => {
let lenCntr = 0, resolveCntr = 0;
for (let p of promises) {
++lenCntr;
Promise.resolve(p).then(val => {
++resolveCntr;
// if we're done with all of them,
// then this val is the last value we should resolve with
if (resolveCntr === lenCntr) {
resolve(val);
}
}).catch(reject);
}
if (lenCntr === 0) {
reject(new Error("promises argument must be an iterable with at least one element"));
}
});
}
const p1 = new Promise ((resolve, reject) => {
setTimeout(() => resolve("First Promise Resolved"), 2000);
});
const p2 = new Promise ((resolve, reject) => {
setTimeout(() => resolve("Second Promise Resolved"), 3000);
});
const p3 = new Promise ((resolve, reject) => {
setTimeout(() => resolve("Third Promise Resolved"), 1000);
});
const promiseList = [p1, p2, p3];
promiseLast(promiseList).then(result => {
console.log(result);
}).catch(err => {
console.log(err);
});
关于实施的一些注意事项:
由于此实现可以接受任何任意可迭代(如
Promise.all()
),因此它不假设存在 .length
属性。因此,它在迭代时计算长度。
像
Promise.all()
一样,如果任何承诺被拒绝,这将被拒绝。
这将可迭代值包装在
Promise.resolve(p)
中,以便迭代也可以包含普通值(再次就像使用 Promise.all()
一样),并且我们仍然可以对每个值调用 .then()
和 .catch()
,而不会出现错误或出现大量错误。类型检查和特殊代码。