如何尝试捕获封装在 Promise.all 中的异步事件处理程序中调用的递归函数

问题描述 投票:0回答:1

我想做的是同时上传多个文件块,然后如果失败则重试每个单独的块 5 次,我已经在 ts Playground 中重新创建了此示例代码,它的工作原理与我的实际代码完全一样,我为简洁起见,省略了使用 XMLHttpRequest 的操作。

这是我的示例代码:

class FileUploader {
    onSuccess: ((this: FileUploader) => void) | null;
    onFail: ((this: FileUploader) => void) | null;

    constructor() {
        this.onSuccess = null;
        this.onFail = null;
    }

    run() {
        // const num = Math.random();
        // if (num > 0.4) {
        //     this.onGood?.();
        // } else {
        //     this.onBad?.();
        // }
        // the above code simulated a request failing or succeding.
        this.onFail?.();
    }
}



async function uploadFile(name: string, retryCount = 0) {
    return new Promise<void>(async (resolve, reject) => {
        const runner = new FileUploader();
        runner.onSuccess = async () => {
            await new Promise((res) => setTimeout(res, 500));
            resolve();
        }
        runner.onFail = async () => {
            if (retryCount < 5) {
                console.log(`Ran ${name}, ${retryCount}`);
                const newDelay = Math.pow(2, retryCount) * 100;
                await new Promise((res) => setTimeout(res, newDelay));
                await uploadFile(name, retryCount + 1);
            }
            console.log("rejected", name);
            reject("error");
        }
        runner.run();
    });
}

async function main() {
    try {
        await Promise.all([uploadFile("file1"), uploadFile("file2"), uploadFile("file3")])
        console.log("success")
    }
    catch (ex) {
        console.log("error")
        console.log(ex);
    }
}

main();

我想做的是捕获主函数中的错误,我该怎么做?

javascript typescript asynchronous async-await promise
1个回答
0
投票

使用

Promise
构造函数 很棘手,通常不推荐。请参阅使用异步函数调用创建新的 Promise 是不好的做法吗?。主要问题之一是,如果出现问题,很容易无法拒绝承诺。事实上,当你内心深处的承诺被拒绝并且
uploadFile()
拒绝时,那就行

await uploadFile(name, retryCount + 1);

将在

Promise
构造函数中抛出错误。这与拒绝承诺不同。你不能拒绝这个承诺,除非你真的打电话给
reject()
。避免这种情况的一种方法是使用 catch()
 构造函数中的 
uploadFile()
函数来
reject
 拒绝任何 
Promise

await uploadFile(name, retryCount + 1).catch(reject); 

一旦进行此更改,您将看到所有拒绝都冒出来,然后是拒绝

Promise.all()
:

[LOG]: "rejected",  "file1"  // 5 
[LOG]: "rejected",  "file1"  // 4
[LOG]: "rejected",  "file1"  // 3
[LOG]: "rejected",  "file1"  // 2
[LOG]: "rejected",  "file1"  // 1
[LOG]: "rejected",  "file1"  // 0
[LOG]: "error message", "error" 

这就是所问问题的答案。


再次,您应该重新考虑在

new Promise()
内部处理 Promise 的任何代码,特别是考虑到错误处理是多么容易出错。但由于这超出了所提出问题的范围,我不会进一步离题。

Playground 代码链接

© www.soinside.com 2019 - 2024. All rights reserved.