1

I am chaining two calls to a function that uses fetch and returns a promise.

The calls sometimes arrive in the wrong order, reversed.

I assume my function code is wrong, derived from a bad understanding of either promises, fetch, or both.

This is the function code, simplified:

function shop(id) {
  return new Promise(function(resolve, reject) {
    fetch('/shop', {
      method: 'post',
      body: JSON.stringify({id: id}) ,
      headers: {'Content-type': 'application/json '}
      }).then(function (response) {
        return response.json();
      }).then(function (data) {
        console.log(data);
        resolve(data);
      })
  })
}

I chain the function in this manner:

shop('potatoe')
.then(shop('mushrooms'));

As explained, these two sometimes arrive in the wrong order, with mushrooms being shopped before potatoes.

May I have my returns or resolve() wrongly written in the shop() function?

Thank you for your help.

Jaume Mal
  • 546
  • 5
  • 21
  • 1
    `.then` takes a callback as its argument, while `shop('mushrooms')` is a promise. You want `() => shop('mushrooms')` – Bergi Mar 04 '21 at 21:00
  • 1
    Also avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! – Bergi Mar 04 '21 at 21:01
  • I would be very grateful if you could give an example of how the code matches such antipattern. Having fetch, with its own chain, within the promise, confuses me. – Jaume Mal Mar 04 '21 at 21:05
  • Yes, having `fetch` with it promise chain within the `new Promise` executor is exactly the problem - it's confusing and doesn't handle errors properly. Just write `function shop(id) { return fetch(…).then(…).then(function (data) { console.log(data); return data; }); }` – Bergi Mar 04 '21 at 21:07
  • This meaning I don't need to resolve fetch, as it resolves itself internally when returning ? – Jaume Mal Mar 04 '21 at 21:09
  • Every promise is responsible for resolving itself internally, regardless what you do with it (`return`ing, chaining `.then()`) or not. – Bergi Mar 04 '21 at 21:12
  • Thank you very much, feel free to add an answer. – Jaume Mal Mar 04 '21 at 21:14

1 Answers1

1

The main issue is that you call shop('mushrooms') immediately, synchronously. You didn't pass a callback to the then method, but instead executed what would be the intended callback. So change the main code to:

shop('potatoe')
.then(() => shop('mushrooms'));

This solves your problem.

However, you are creating a useless promise in your function. The fetch().then().then() chain already returns a promise; you don't need to create yet another one. Read about the promise constructor antipattern.

So remove this new Promise wrapper, and remove the final .then() call which was only there to call resolve:

function shop(id) {
    // return the promise returned by this promise chain:
    return fetch('/shop', {
        method: 'post',
        body: JSON.stringify({id: id}) ,
        headers: {'Content-type': 'application/json '}
    }).then(function (response) {
        return response.json();
    });
}
trincot
  • 317,000
  • 35
  • 244
  • 286