如何解决如何在打字稿中仅返回已解决的承诺,而忽略错误?
我已经创建了该函数,该函数应采用Promises数组,并且仅返回已解决的Promises。错误必须忽略。因此,似乎有点像Promise.all,但没有错误。问题是用打字稿正确编写函数。以前,仅使用JS可以达到预期的效果。
function promiseIgnoreErrors<T> (arrayOfPromise: Array<T>) {
const isArrayEmpty =
Array.isArray(arrayOfPromise) && arrayOfPromise.length === 0;
return new Promise((resolve,reject) => {
if (isArrayEmpty) reject(new Error('Forever pending array'));
let resolvedArray: Array<T> = []
let resolvedCounter: number = 0;
arrayOfPromise.forEach((promise,index) => {
if (promise instanceof Promise) {
promise
.then((data) => {
resolvedArray[index] = data
resolvedCounter++;
if (arrayOfPromise.length === resolvedCounter) resolve(resolvedArray)
})
.catch(() => {
resolvedCounter++;
if (arrayOfPromise.length === resolvedCounter) resolve(resolvedArray)
})
} else {
resolvedArray[index] = promise
resolvedCounter++;
if (arrayOfPromise.length === resolvedCounter) resolve(resolvedArray)
}
})
});
};
问题简短介绍。我的变量:
const p1 = new Promise((resolve) => setTimeout(() => resolve('JS'),500))
const p2 = 22
const p3 = new Promise((reject) => setTimeout(() => reject(new Error('Oops')),100))
const p4 = new Promise((resolve) => setTimeout(() => resolve('TS'),200))
当我拥有变量并将其作为数组传递时,
promiseIgnoreErrors([p1,p2,p3,Promise.reject(10),p4])
我希望:
Promise {<pending>}
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: Array(3)
// ['JS',22,'TS']
现在我有:
Promise {<pending>}
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: Array(5)
// ['JS',Error: 'Oops,?,'TS']
您可以在控制台中显示我的问题: Playground
我认为问题是这里的泛型,也正是这一行:
let resolvedArray: Array<T> = []
因为它指示返回的表必须包含与输入中相同的元素。也许应该类似于:
let resolvedArray: Array<K> extends T = []
我当然知道上面的行是错误的,但是也许我应该遵循这个想法。或者也许我的功能不正常?
请提供任何帮助!
解决方法
这似乎足够。
这个想法是ERRORED
是一个哨兵对象;如果数组中的一个承诺抛出了,我们将其捕获并将其转换为ERRORED
。
isNotErrored(x)
是一种类型保护功能,可确保TypeScript x
不是哨兵,因此results.filter(isNotErrored)
的类型最终是T[]
,而不是{{1 }}。
(T | '__ERRORED__')[]
例如
const ERRORED = '__ERRORED__';
type ErroredType = typeof ERRORED;
function isNotErrored<T>(x: T | ErroredType): x is T {
return x !== ERRORED;
}
async function promiseIgnoreErrors<T>(promises: Array<Promise<T>>): Promise<Array<T>> {
const results = await Promise.all(promises.map(p => p.catch(() => ERRORED as ErroredType)));
return results.filter(isNotErrored);
}
日志
promiseIgnoreErrors([Promise.resolve(8),Promise.reject("oh no"),Promise.resolve(16)]).then(r => {
console.log(r);
});
忽略拒绝。
编辑:
对于原始输入
[8,16]
这不会进行类型检查,因为并非所有输入都是Promise,这是恕我直言的正确行为。正如评论中所讨论的,裸值应使用const p1 = new Promise((resolve) => setTimeout(() => resolve('JS'),500))
const p2 = 22
const p3 = new Promise((reject) => setTimeout(() => reject(new Error('Oops')),100))
const p4 = new Promise((resolve) => setTimeout(() => resolve('TS'),200))
包装,即
Promise.resolve()
或者您可以在内部执行此操作:
const p2 = Promise.resolve(22)
,
async function promiseIgnoreErrors<T>(arrayOfPromise: Array<T>) {
const promises = await Promise.all(arrayOfPromise.map((p) => promisify(p)))
return promises.filter((v) => v != null)
}
const promisify = <T>(value: T) =>
Promise.resolve(value)
.then((v) => (v instanceof Error ? null : v))
.catch(() => null)
const r = promiseIgnoreErrors([p1,p2,p3,p4,p5])
console.log(r) // Promise { <pending> }
r.then((x) => console.log(x)) // [ 'JS',22,'TS' ]
更新
已删除flatMap版本,以免造成混淆
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。