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

时间:2020-01-03 05:21:05

标签: javascript node.js asynchronous promise async-await

您如何处理无法解决的承诺?

示例:

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 

uncaughtExceptionunhandledRejection未兑现承诺时不返回任何内容。在等待中添加try/catch无效(没有错误)。最后,唯一有效的方法是使用Promise.then而不是await

问题是代码库中充斥着async/await和有时会解决的Promise(取决于条件)

问题:是否可以添加打字机标记来检测缺少的解析/拒绝?还是自动转换所有async/await以使用Promise.then的方式?

使用调试器时,程序在Promise之后停止,并且很难找到哪个函数/诺言缺少解析/拒绝。

重写所有async/await调用以使用Promise.then是我的最后选择。

2 个答案:

答案 0 :(得分:4)

如果您的承诺偶尔不会解决或拒绝,而这不是他们应有的工作方式(通常不是这样),那么您只需要解决该问题即可。确实没有解决方法。正确的解决方法是降到最低级别并修复代码,以使它每次都能可靠地解决或拒绝。


这不是正确的解决方法,但是实现超时包装可以帮助调试,从而为您提供一条日志消息,其中包含类似于堆栈跟踪的超时承诺:

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)]);
}

然后您可以包装任何承诺,而不是:

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

您可以使用:

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

或者,如果您想设置自定义超时值:

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

同样,这是调试代码,以帮助找到需要修复的罪魁祸首并帮助测试修复,而不是浪费代码。

重写所有异步/等待调用以使用Promise。那是我的最后选择。

我完全不知道这对您有什么帮助。如果await从未完成,promise.then()都不会。在这方面,它们是完全相同的。如果承诺从未解决或拒绝,那么.then()处理程序也将不会被调用。

问题是代码库中充斥着异步/等待和有时会解决的Promises(取决于条件)

除了有条不紊的代码审查之外,这里没有捷径可走,找到具有可能永远无法解析或拒绝的代码路径的可疑代码,然后构建单元测试以测试在各种情况下返回promise的每个函数。

一个可能无法解决或拒绝的代码源是一些promise反模式。其中一些是反模式的确切原因是因为它们很容易弄乱。以下是一些参考资料,可能会增加您对可疑代码的敏感性:

Promise Anti-Patterns

Common Promise Anti-Patterns and How to Avoid Them

ES6 Promises: Patterns and Anti-Patterns

答案 1 :(得分:0)

SELECT id, MONTH(start_date) as month, YEAR(start_date ) as year,  DATEDIFF(end_date, start_date ) as days from table-name