UnhandledPromiseRejectionWarning when using Fluture `encaseP` on `fetch`

165 views Asked by At

I have just started using Flutures, and I am trying to fetch some remote data for a visualization with d3.

I created a function which accepts a DOM selector (e.g. #my-chart) and a url (e.g. https://example.com/data.json).

If an error occurs when fetching the data, I have a unary function that shows an error message. If everything goes well, I have a unary function that draws the visualization. For the sake of simplicity, let's suppose that these functions are just console.error and console.log.

const fn = async (selector, url) => {
// convert fetch (which returns a Promise) into a function that 
returns a Future
const fetchf = Future.encaseP(fetch);

fetchf(url)
  .chain(res => Future.tryP(_ => res.json()))
  .fork(console.error, console.log);
}

Apparently I am missing something when wrapping fetch in a Future, because I get this warning:

UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch().

If I had to use async/await I would write something like this, which would not give me any warning.

const fn = async (selector, url) => {
  let res;
  try {
    res = await fetch(url);
  } catch (err) {
    console.error(err);
    return;
  }
  let data;
  try {
    data = res.json();
  } catch (err) {
    console.error(err);
    return;
  }
  console.log(data);
};
1

There are 1 answers

1
Avaq On BEST ANSWER

It seems two things are going on here:

  1. The data.json() function is not supposed to be wrapped inside tryP, because according to your second not broken example, it returns synchronously (there is no await). This would cause Fluture to raise a TypeError (because it expects to see a Promise, but gets a JSON value). Although, knowing the fetch API, data.json() typically does return a Promise, so it might also be your second example is broken, and something else is going on. Whatever it is, I suspect that an unexpected Error is being thrown somewhere. Do you see any other error messages in your console, besides the one you posted?
  2. I did some testing, and it does seems to be true - when Fluture raises or catches a TypeError after a successful encaseP, it seems the original Promise manages to catch that error, and trigger the unhandled rejection. This appears to be a regression bug in Fluture, and I will be fixing it soon. In the meantime, if we get to the bottom of what's throwing your error, you will be able to continue without depending on said fix.

EDIT: I've opened a PR to fix the second issue: https://github.com/fluture-js/Fluture/pull/310

EDIT2: The fix has been released under version 10.3.1. Using that version should give you more insights in what's happening with issue 1.