简体   繁体   English

等待/异步如何处理未解决的承诺

[英]await/async how to handle unresolved promises

How do you handle promises that do not resolve?你如何处理没有解决的承诺?

Example:例子:

class Utils {
    static async thisFunctionOnlyResolvesWhenPassed2AndNeverRejects(number: number) {
        return new Promise((resolve, reject) => {
            if(number === 2) {
                resolve('ok')
            }
        })
    }
}

console.log(await Utils.thisFunctionOnlyResolvesWhenPassed2AndNeverRejects(2))
// this will print "ok" because 2 is passed and the promise is resolved

console.log(await Utils.thisFunctionOnlyResolvesWhenPassed2AndNeverRejects(5))
// this will crash the program silently 

uncaughtException and unhandledRejection return nothing when the promise is unresolved. uncaughtExceptionunhandledRejection当承诺未解决时不返回任何内容。 Adding a try/catch around the await doesn't work (no errors).在等待周围添加try/catch不起作用(没有错误)。 Finally, the only thing that works is using Promise.then instead of await .最后,唯一有效的是使用Promise.then而不是await

Problem is the code base is riddled with async/await and Promises that sometimes resolve (depending on conditions)问题是代码库充斥着async/await和有时会解决的承诺(取决于条件)

Question : Is there a typescript flag I can add to detect a missing resolve/reject?问题:是否可以添加打字稿标志来检测丢失的解析/拒绝? or maybe an automated way to transpile all the async/await to use Promise.then ?或者也许是一种将所有async/await Promise.then为使用Promise.then的自动化方式?

When using a debugger, the program stops after the Promise and it is difficult to find which function/promise has a missing resolve/reject.使用调试器时,程序在 Promise 之后停止,很难找到哪个函数/promise 丢失了 resolve/reject。

Rewriting all the async/await calls to use Promise.then is my last resort.重写所有async/await调用以使用Promise.then是我最后的手段。

If you have promises that occasionally don't resolve or reject and that's not the way they are supposed to work (which it usually isn't), then you just have to fix that.如果您的承诺偶尔无法解决或拒绝,并且这不是他们应该工作的方式(通常不是),那么您只需要解决这个问题。 There really is no work-around.真的没有解决方法。 The proper fix is to get down to the lowest level and fix the code so it reliably resolves or rejects every time.正确的解决方法是深入到最低级别并修复代码,以便它每次都能可靠地解决或拒绝。


This is not the proper fix, but implementing a timeout wrapper could help with debugging giving you a log message with some semblance of a stack trace for a timed out promise:这不是正确的修复,但实现超时包装器可以帮助调试,为您提供一条日志消息,其中包含一些类似于超时承诺的堆栈跟踪:

function rejectT(t) {
    // create potential error here for better opportunity at stack trace
    let e = new Error("Promise timed out");
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(e);
            reject(e);
        }, t);
    });
}

function timeout(p, t = 5000) {
    return Promise.race([p, rejectT(t)]);
}

You can then wrap any promise such that instead of:然后,您可以包装任何承诺,而不是:

fn().then(...).catch(...)

You can use:您可以使用:

timeout(fn()).then(...).catch(...);

Or, if you want to set a custom timeout value:或者,如果您想设置自定义超时值:

timeout(fn(), 1000).then(...).catch(...);

Again, this is debugging code to help find the culprits that need fixing and to help test fixes, not to bandaid your code.同样,这是调试代码以帮助找到需要修复的罪魁祸首并帮助测试修复,而不是捆绑您的代码。

Rewriting all the async/await calls to use Promise.then is my last resort.重写所有 async/await 调用以使用 Promise.then 是我最后的手段。

I don't see how this is going to help at all.我根本看不出这会有什么帮助。 If await never finishes, neither will promise.then() .如果await永远不会完成,则promise.then()也不会完成。 They are exactly the same in that regard.他们在这方面完全相同。 If the promise never resolves or rejects, then the .then() handler will never get called either.如果承诺永远不会解决或拒绝,那么.then()处理程序也永远不会被调用。

Problem is the code base is riddled with async/await and Promises that sometimes resolve (depending on conditions)问题是代码库充斥着 async/await 和有时会解决的承诺(取决于条件)

There's no shortcut here other than methodical code review to find suspect code that has code paths that may never resolve or reject and then building unit tests to test every function that returns a promise in a variety of conditions.除了有条不紊的代码审查之外,这里没有其他捷径,可以找到具有永远无法解析或拒绝的代码路径的可疑代码,然后构建单元测试来测试在各种条件下返回承诺的每个函数。

One likely source of code that never resolves or rejects are some of the promise anti-patterns.一种可能永远不会解析或拒绝的代码来源是一些 promise 反模式。 The precise reason some of them are anti-patterns is because they can be very easy to mess up.其中一些是反模式的确切原因是因为它们很容易搞砸。 Here are a few references that might spike your sensitivity to suspect code:以下是一些可能会激发您对可疑代码的敏感性的参考资料:

Promise Anti-Patterns Promise 反模式

Common Promise Anti-Patterns and How to Avoid Them 常见的 Promise 反模式以及如何避免它们

ES6 Promises: Patterns and Anti-Patterns ES6 Promises:模式和反模式

 async function thisFunctionOnlyResolvesWhenPassed2AndNeverRejects(number) { return new Promise((resolve, reject) => { if (number === 2) { resolve('ok') } else { reject('error:' + number) } }) } (async() => { try { console.log(await thisFunctionOnlyResolvesWhenPassed2AndNeverRejects(2)) // this will print "ok" because 2 is passed and the promise is resolved } catch (e) { console.error(e); } try { console.log(await thisFunctionOnlyResolvesWhenPassed2AndNeverRejects(5)) // this will crash the program silently } catch (e) { console.error(e); } })()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM