当前位置: 首页 > 知识库问答 >
问题:

在以后的某个时间捕获拒绝promise[副本]

麹凯捷
2023-03-14

我以后如何检索promise的结果?在一次测试中,我在发送进一步请求之前检索了一封电子邮件:

const email = await get_email();
assert.equal(email.subject, 'foobar');
await send_request1();
await send_request2();

如何在缓慢的电子邮件检索过程中发送请求?

起初,我考虑过以后再发邮件:

// This code is wrong - do not copy!
const email_promise = get_email();
await send_request1();
await send_request2();
const email = await email_promise;
assert.equal(email.subject, 'foobar');

如果get_-email()成功,则此操作有效,但如果get_-email()在相应的等待之前失败,并且出现完全正确的未处理PromisejectionWarning,则此操作失败。

当然,我可以用promise。全部,如下所示:

await Promise.all([
    async () => {
        const email = await get_email();
        assert.equal(email.subject, 'foobar');
    },
    async () => {
        await send_request1();
        await send_request2();
    },
]);

然而,这使得代码更难阅读(它看起来更像基于回调的编程),特别是如果以后的请求实际上依赖于电子邮件,或者有一些嵌套正在进行。有没有可能存储promise的结果/异常,并在以后等待它?

如果需要的话,这里有一个模拟的测试用例,有时失败,有时工作,随机计时。它绝不能输出未经处理的PromiserEjectionWarning。

共有3个答案

庄瀚玥
2023-03-14

所以,我想解释一下为什么我们在节点中会这样做。js:

// Your "incorrect code" from before
const email_promise = get_email(); // we acquire the promise here
await send_request1(); // if this throws - we're left with a mess
await send_request2(); // if this throws - we're left with a mess
const email = await email_promise;
assert.equal(email.subject, 'foobar');

也就是说,我们这样做的原因是不处理“多次拒绝,可能没有清理”的场景。我不知道你是如何得到Promise.all的长代码的,但是:

await Promise.all([
    async () => {
        const email = await get_email();
        assert.equal(email.subject, 'foobar');
    },
    async () => {
        await send_request1();
        await send_request2();
    },
]);

实际上可以是这样的:

let [email, requestData] = await Promise.all([
  get_email(),
  send_request1().then(send_request2)
]);
// do whatever with email here

我可能会这么做。

束新
2023-03-14

如果保证稍后会处理promise拒绝,则可以使用dummycatch链接promise,以抑制未处理拒绝的检测:

try {
    const email_promise = get_email();
    email_promise.catch(() => {}); // a hack
    await send_request1();
    await send_request2();
    const email = await email_promise;
    assert.equal(email.subject, 'foobar');
} catch (err) {...}

这种方法的问题是,有两个并发例程,但代码没有表达这一点,这是一种解决方法,通常使用Promise来完成。全部。这种变通方法之所以可行,唯一的原因是只有两个例程,其中一个(get_email)需要与链接,然后/wait,只有一次,所以其中的一部分(assert)可以推迟。如果有3个或3个以上的例程,或者例程涉及多个,那么/等待,问题就会更加明显。

以防promise。所有都引入了不需要的lambda嵌套级别,这可以通过将例程编写为命名函数来避免,即使它们没有在其他地方重用:

async function assertEmail() {
    const email = await get_email();
    assert.equal(email.subject, 'foobar');
}

async function sendRequests() {
    await send_request1();
    await send_request2();
}

...

try {
    await Promise.all([assertEmail(), sendRequests()]);
} catch (err) {...}

这会产生干净的控制流和冗长但更易于理解和测试的代码。

韦安顺
2023-03-14
const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms));
const send_request1 = () => wait(300), send_request2 = () => wait(200);
async function get_email() {
    await wait(Math.random() * 1000);
    if (Math.random() > 0.5) throw new Error('failure');
    return {subject: 'foobar'};
}

const assert = require('assert');
async function main() {
    // catch possible error
    const email_promise = get_email().catch(e => e);
    await send_request1();
    await send_request2();
    // wait for result
    const email = await email_promise;
    // rethrow eventual error or do whatever you want with it
    if(email instanceof Error) {
      throw email;
    }
    assert.equal(email.subject, 'foobar');
};

(async () => {
    try {
        await main();
    } catch(e) {
        console.log('main error: ' + e.stack);
    }
})();
 类似资料:
  • 我编写了一个函数,它返回异步逐行读取文件的promise,但问题是如果文件不存在,就会抛出错误,应用程序崩溃。我已经将代码包围在try-catch块中,但是代码执行从未进入catch块,而是终止。 其次,我可以拒绝promise,然后从promise中返回json对象吗? 像

  • 我在想什么时候我该拒绝一个promise。我发现了几个关于这个话题的问题,但找不到合适的答案。我什么时候应该拒绝promise? 本文http://howtonode.org/6666a4b74d7434144cff717c828be2c3953d46e7/promises 说: 解析:一个成功的promise是“已解析”的,它调用正在等待的成功侦听器,并记住为附加的未来成功侦听器解析的值。分辨率

  • 我正在使用Firebase云消息服务辅助角色处理后台推送通知。 当通知(其中包含一些数据的URL)被点击,我想要么: 焦点窗口,如果它已经在所需的URL 导航到URL并聚焦它,如果已经有一个活动的选项卡打开 如果上述条件都不满足,则打开URL的新窗口 点1和3与下面的SW代码一起工作。 出于某种原因,第2点不起作用。promise被拒绝,原因是: 我认为这可能是由于缺少https,但从我的阅读来看

  • 本文介绍了单个promise组合器: 但我没有看到的是,一种运行所有promise的方法,但不是在个人promise被拒绝时短路。我如何确保所有的promise都得到履行,但我能处理拒绝和所有promise的解决?

  • 我得到这个错误- (节点:18420)未处理的PromisejectionWarning:TypeError:无法读取未定义的属性“name” (节点:18420)未处理的PromisejectionWarning:未处理的promise拒绝。此错误源于在没有catch块的情况下抛出异步函数的内部,或者拒绝使用未处理的promise。catch()。要在未处理的promise拒绝时终止节点进程,请

  • 我正在尝试编写一个jasmine测试,它有一个间谍, 是一个许诺列表。前几次承诺是拒绝,最后一次是成功。虽然测试顺利通过,但Node抱怨如下: 我的代码非常直接:我创建一个间谍,将它注入到我的代码中,调用我的代码,这将循环调用我的间谍直到它不拒绝,然后监视它被调用了5次。间谍是这样的: 被测试的代码在它的链中最后一个空的 来验证我没有引起那里的问题。AFICT,问题是Node看到我在执行 ,并认为