I'm doing some basic asynchronous operations using async/await
in TypeScript but TSLint is throwing mysterious error messages for these two functions below. Has anyone encountered these errors before? On the error output the governing rule is not mentioned, so I don't understand what's causing these. Any ideas would be greatly appreciated.
The main request:
import * as rp from 'request-promise'
export function getRequest(address: rp.Options): rp.RequestPromise {
return rp(address)
}
Exported async function:
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)
}
}
This gets: Promises must be handled appropriately
and await of non-Promise
for line #3.
The simple function that uses this export is:
client.on('message', message => {
if (message.content === 'green') {
getStatus(message)
}
})
This also gets Promises must be handled appropriately
.
Additional information:
Even though the error message doesn't mention it, this seems to be the governing rule for Promises must be handled appropriately
: https://palantir.github.io/tslint/rules/no-floating-promises/
And this Issue mentions await of non-Promise
: https://github.com/palantir/tslint/issues/2661
rp
. So I used this: export function getRequest(address: rp.Options): rp.RequestPromise { return rp(address) }
This satisfies the IDE but I'm still getting exactly the same errors in the initial post.
That's a crappy error message. A better one might be,
every expression of type Promise
must end with a call to .catch
or a call to .then
with a rejection handler (source).
So, for example, if you do
PromiseFunction()
.catch(err => handle(err))
.then(() => console.log('this will succeed'))
then you will still have a tslint problem, because the type of .then(...)
is a promise, and it has to end with a catch. The fix would be appending a .catch
clause, for example,
PromiseFunction()
.catch(err => handle(err))
.then(() => console.log('this will succeed'))
.catch(() => 'obligatory catch')
or just disabling tslint for that line via:
PromiseFunction()
.catch(err => handle(err))
// tslint:disable-next-line:no-unsafe-any
.then(() => console.log('this will succeed'))
Alternatively, you could reverse the order of the .then
and .catch
statements. However, that stops the .then
from executing if an error does occur, which you presumably want if you encountered this problem.
Sometimes you might want to call the promise, but you don't need to do anything with the response. A route change or something else.
so instead of:
promiseFunction().then().catch()
try/catch async/await
you can do:
void promiseFunction();
As per the comments on the correct use of void
please read: IgnoreVoid
Use at your own convenience :)
void
syntax
void 0
is shorter than undefined
. And it is used as "pure" undefined. In clean code it can be confusing and it entices to disguise problems. There are many articles in the web. (just google it. "eslint no-void") The words here are limited. :D Finally it's up to you (the developer) how to write code and for what context. (professional clean code or amateur. The freedom in JavaScript is a blessing and a curse at the same time.)
void
. You can use inline comments to disable the rule on a case by case basis, but I personally don't use void
for anything else, so I find /* checked, can't reject */ void promiseFunc();
perfectly legible.
I have got the same exception when i have created firebase-function
using firebase-tool
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 );
})
This code doesn not compiled and return
ERROR: /src/index.ts[22, 5]: Promises must be handled appropriately
I have changed the places of catch
and then
.
ref.once(...).then(...).catch(...)
This code is work, i am sorry but I don't have any explanation
So much amazing when app return the some error without catch
block even according firebase doc
not mentioned that catch
is required.
Your getStatus
function is defined to return a promise:
// All functions marked as async returns a promise:
async function getStatus(message: Message) {/* ... */}
But you called getStatus
without calling it's then:
getStatus(message)
Therefore the compiler thinks you've forgotten to handle your async code. All you need to do is call .then()
:
getStatus(message).then(() => console.log('done'));
getStatus(message).then(() => console.log('done'))
still gets Promises must be handled appropriately
.
.catch()
as well? getStatus().then().catch()
.catch()
and a try/catch
for the invocation of getStatus()
still the same error as my first comment.
If you are writing a void async function with typescript-eslint, you will be getting a complaint if you write async functions without await, it's easy to forget especially for the last line of the function.
const sendSyncPlayCommandToWatchers = async (): Promise<void> => {
...
someAsyncFunction()
}
You will get
error Promises must be handled appropriately @typescript-eslint/no-floating-promises
You need to add the await keyword to the last line (or make sure you handle the promise with try/catch as mentioned in previous replies
const sendSyncPlayCommandToWatchers = async () => {
...
await someAsyncFunction()
}
I think this will also help getting a better stack trace when debugging.
I think this problem is fixable by awaiting the getStatus function, since its an async function. The message is saying it clearly, but the line number causes confusion. To be honest it also took me some time.
You can solve this lint error by this change in code:
client.on('message', message => {
if (message.content === 'green') {
await getStatus(message)
}});
In my opinion it's not a good idea to switching these specific errors off. They are useful because in the other way you would not run the code async.
await
, getStatus
would not hold up the thread. The author may not want to delay subsequent execution. This could needlessly hold up an app.
Success story sharing
no-floating-promises
rule and I agree the error message isn't great. If you want to send a PR with a better description I'm all for it!