I have seen many youtube videos/courses/"books" on promises with fetch, but they didn't help. This is just confusing.

I understand this bit:

fetch("some url/file")   // get "data" from some API and it returns a promise

.then( res => res.json()) // this is a promise but not the raw data that we need

.then(data => console.log(data) // with this I will actually access the actual data

.catch( err => console.log(err) // this is if errors exists but ONLY if It can't open the actual site, like their server is dead or whatever, I know that with an IF statements I can check if the status is 200 and that can work with errors.

I was reading more about it and a site said "The new Promise() constructor should only be used for legacy async tasks, like usage of setTimeout or XMLHttpRequest. A new Promise is created with the new keyword and the promise provides resolve and reject functions to the provided callback:"" ,but then what about resolve and reject? Do I even need them?

Then, I read on stackoverflow that if you are fetching, you don't need to make a "new Promise" because fetch already returns a promise(though in the stackoverflow example the person was writing it like this, in a variable"

function get(url) {

console.log('Making fetch() request to: ' + url);

let promise = new Promise((resolve, reject) => {

fetch(url).then  // etc etc
")

So the main questions are:

  1. What about "new Promise"? What is it? Do I need it? When? Talk to me about it.

  2. If I need "new Promise", do I put it into a variable (let test = new Promise) or do I return it in a function (function test(){ return new Promise}) //etc etc, what is the difference?

  3. If I need "new Promise", when do I resolve and reject? WHAT do I resolve/reject?

If you want to answer these questions with an in depth link, explaining it, feel free.

Thank you for your time.

upvote
  flag
Minor point: You're missing a ) at the end of .then(data => console.log(data). – T.J. Crowder
upvote
  flag
Simple rule of thumb. If a method has a .then() property...it is already a promise – charlietfl
upvote
  flag
I'm glad I switched to async await, especially for fetch. It's just so much more readable! async loadData(){this.data = (await fetch(url)).json()} That's it!!! – Kokodoko

2 Answers 11

up vote 2 down vote accepted

Your comments on that fetch code are mostly correct, except that because the catch is at the end of the chain, it doesn't only receive failures from the original fetch; if there's an error thrown within one of the then callbacks preceding it (or a promise returned from one that ultimately rejects), it'll see that error. For instance, with this code if the fetch succeeds the catch handler receives the error thrown by the then callback:

fetch(/*...*/)
.then(response => throw new Error("fail"))
.catch(err => {
    // Either gets error from `fetch` or failure from `then` above
});

Similarly, in your quoted code, if the promise returned by response.json() rejects (can't read the body, invalid JSON, etc.), your catch handler will see that rejection (error).

...what about resolve and reject? Do I even need them?

Not in that code, no.

1. What about "new Promise"? What is it? Do I need it? When?

You need it when you don't have a promise already and you need a promise chain. You don't need it when you have a promise already (such as the one from fetch) and need a promise chain.

2. If I need "new Promise", do I put it into a variable (let test = new Promise) or do I return it in a function (function test(){ return new Promise}) //etc etc, what is the difference?

There's nothing special about promises in that regard. If you need to refer to it later within the same scope, use a variable. If not, you can return it directly (if returning it).

3. If I need "new Promise", when do I resolve and reject? WHAT do I resolve/reject?

You call resolve when whatever non-promise activity you're doing completes. You pass it the value that activity generated (if there is one).

You call reject when whatever non-promise activity you're doing fails. You pass it the same thing you'd use with throw: An error of some kind. (Typically by creating it as an actual error, e.g., new Error(...)).

More reading on new Promise: What is the explicit promise construction antipattern and how do I avoid it?

If you want to combine fetch and response.json() you do not have to return a new Promise because fetch is already a promise. You can just return the fetch().then(...)

For example

const fetchJson = url =>
  fetch(url).then(r=>g.json());

You can use new Promise when you want to call an API that takes callbacks and turn it into a promise instead.

For example:

const classicApiToPromise = arg =>
  new Promise(
    (resolve,reject)=>
      classicApi(
        arg,
        (data,err)=>//classic callback
          (err)
            ? reject(err)
            : resolve(data)
      )
  );

Not the answer you're looking for? Browse other questions tagged or ask your own question.