react-native: JS exceptions are hidden from developer when using Promises (async functions)

Take the following example, which (correctly) produces a redbox:

IntentAndroid.canOpenURL(url, (canOpen) => {
  // Some code that can throw ...
  throw new Error('This should redbox');
});

The Java signature is:

@ReactMethod
public void canOpenURL(String url, Callback callback)

Now change this to an async function:

@ReactMethod
public void canOpenURL(String url, Promise promise)

IntentAndroid.canOpenURL(url).then((canOpen) => {
  // Some code that can throw ...
  throw new Error('This should redbox');
});

No redbox is shown and nothing is logged which is in my opinion very poor developer experience. We’ve all been there - you’re trying to debug a program which doesn’t work but since there are no error messages and you have no idea what’s wrong.

The way to “fix” this is to call done():

IntentAndroid.canOpenURL(url).then((canOpen) => {
  // Some code that can throw ...
  throw new Error('This should redbox');
}).done();  // Now throws and produces a redbox

But this is super easy to forget 😦

For now, I’ll go with a callback in the IntentAndroid. Feel like we need to find a good solution to this problem first before we migrate all APIs to async functions.

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 29 (26 by maintainers)

Commits related to this issue

Most upvoted comments

you should be able to paste this code into your app, and throw an error: https://github.com/facebook/react-native/blob/c6b96c0df789717d53ec520ad28ba0ae00db6ec2/Libraries/Promise.js#L17-L49

In case this does nothing, use setImmediate to throw outside of the promise rejection handler

  • unfortunately, done() is not part of the es2015 standard
  • maybe we should extend our internal promise implementation so that it produces a red box if no rejection handler is registered.