我正在使用 TypeScript 中的 async/await
执行一些基本的异步操作,但 TSLint 正在为下面的这两个函数抛出神秘的错误消息。有没有人遇到过这些错误?在错误输出中没有提到管理规则,所以我不明白是什么导致了这些。任何想法将不胜感激。
主要要求:
import * as rp from 'request-promise'
export function getRequest(address: rp.Options): rp.RequestPromise {
return rp(address)
}
导出的异步函数:
export async function getStatus(message: Message) {
try {
const res = await getRequest(address)
if (res.ready) {
message.reply('...')
} else {
message.reply('...')
}
} catch (err) {
message.reply(err)
}
}
对于第 3 行,这将得到:Promises must be handled appropriately
和 await of non-Promise
。
使用此导出的简单函数是:
client.on('message', message => {
if (message.content === 'green') {
getStatus(message)
}
})
这也得到 Promises must be handled appropriately
。
附加信息:
即使错误消息没有提到它,这似乎是 Promises must be handled appropriately
的管理规则:https://palantir.github.io/tslint/rules/no-floating-promises/
这个问题提到了await of non-Promise
:https://github.com/palantir/tslint/issues/2661
rp
实际返回的内容不兼容。所以我使用了这个:export function getRequest(address: rp.Options): rp.RequestPromise { return rp(address) }
这满足了 IDE,但我在最初的帖子中仍然遇到完全相同的错误。
这是一个糟糕的错误信息。更好的可能是,
每个 Promise
类型的表达式都必须以调用 .catch
或使用拒绝处理程序调用 .then
结束 (source)。
所以,例如,如果你这样做
PromiseFunction()
.catch(err => handle(err))
.then(() => console.log('this will succeed'))
那么你仍然会有一个 tslint 问题,因为 .then(...)
的类型是一个承诺,它必须以一个 catch 结尾。修复将附加一个 .catch
子句,例如,
PromiseFunction()
.catch(err => handle(err))
.then(() => console.log('this will succeed'))
.catch(() => 'obligatory catch')
或者只是通过以下方式禁用该行的 tslint:
PromiseFunction()
.catch(err => handle(err))
// tslint:disable-next-line:no-unsafe-any
.then(() => console.log('this will succeed'))
或者,您可以颠倒 .then
和 .catch
语句的顺序。但是,如果确实发生错误,这会阻止 .then
执行,如果您遇到此问题,您可能需要这样做。
有时你可能想调用 Promise,但你不需要对响应做任何事情。路线改变或其他。
所以而不是:
promiseFunction().then().catch()
try/catch async/await
你可以做:
void promiseFunction();
根据有关正确使用 void
的评论,请阅读:IgnoreVoid
在您自己方便的时候使用 :)
void
语法的引用会很方便
void 0
比 undefined
短。它被用作“纯”未定义。在干净的代码中,它可能会令人困惑,并且会诱使人们掩盖问题。网上有很多文章。 (只是谷歌它。“eslint no-void”)这里的话是有限的。 :D 最后,由您(开发人员)决定如何编写代码以及在什么上下文中编写代码。 (专业干净的代码或业余爱好者。JavaScript 中的自由既是福也是祸。)
void
的部分。您可以根据具体情况使用内联注释来禁用规则,但我个人不会将 void
用于其他任何事情,因此我发现 /* checked, can't reject */ void promiseFunc();
非常清晰。
当我使用 firebase-tool
创建 firebase-function
时,我遇到了同样的异常
const ref = admin.database().ref("path/to/database/object");
ref.once("value").catch(error =>{ // line 22
response.send( error() );
}).then( snapshot =>{
response.send( snapshot.val );
})
此代码未编译且return
ERROR: /src/index.ts[22, 5]: Promises must be handled appropriately
我已更改 catch
和 then
的位置。
ref.once(...).then(...).catch(...)
此代码有效,对不起,但我没有任何解释
当应用程序返回一些没有 catch
块的错误时,即使根据 firebase doc
也没有提到需要 catch
,这真是太神奇了。
您的 getStatus
函数被定义为返回一个承诺:
// All functions marked as async returns a promise:
async function getStatus(message: Message) {/* ... */}
但是您调用了 getStatus
而没有调用它:
getStatus(message)
因此编译器认为你忘记了处理你的异步代码。您只需调用 .then()
:
getStatus(message).then(() => console.log('done'));
getStatus(message).then(() => console.log('done'))
仍然是 Promises must be handled appropriately
。
.catch()
? getStatus().then().catch()
.catch()
和 try/catch
来调用 getStatus()
仍然与我的第一条评论相同的错误。
如果你正在使用 typescript-eslint 编写一个 void 异步函数,如果你在没有 await 的情况下编写异步函数,你会收到抱怨,特别是函数的最后一行很容易忘记。
const sendSyncPlayCommandToWatchers = async (): Promise<void> => {
...
someAsyncFunction()
}
你会得到
必须正确处理错误承诺 @typescript-eslint/no-floating-promises
您需要将 await 关键字添加到最后一行(或确保您使用 try/catch 处理承诺,如之前的回复中所述
const sendSyncPlayCommandToWatchers = async () => {
...
await someAsyncFunction()
}
我认为这也将有助于在调试时获得更好的堆栈跟踪。
我认为这个问题可以通过等待 getStatus 函数来解决,因为它是一个异步函数。消息说得很清楚,但行号会引起混淆。老实说,我也花了一些时间。
您可以通过以下代码更改来解决此 lint 错误:
client.on('message', message => {
if (message.content === 'green') {
await getStatus(message)
}});
在我看来,关闭这些特定错误并不是一个好主意。它们很有用,因为以另一种方式您不会异步运行代码。
await
之前,getStatus
不会阻止线程。作者可能不想耽误后续的执行。这可能会不必要地阻止应用程序。
no-floating-promises
规则,并且我同意错误消息不是很好。如果您想发送具有更好描述的 PR,我完全赞成!