6

I have following code which I using for handling Magento 2 REST API.

return new Promise((resolve, reject) => {
      fetch(uri, { method, headers, body: JSON.stringify(data) })
        .then(response => {
          return response.json();
        })
        .then(responseData => {
          resolve(responseData);
        })
        .catch(error => {
          reject(error);
        });
    });

And I want to add response status checking, so I've started like this

return new Promise((resolve, reject) => {
      fetch(uri, { method, headers, body: JSON.stringify(data) })
        .then(response => {
          return {
            data: response.json(),
            ok: response.ok,
            status: response.statusText
          };
        })
        .then(responseResult => {
          if (responseResult.ok) {
            resolve(responseResult.data);
          } else {
            const error = responseResult.status || responseResult.data.message;
            reject(error);
          }
        })
        .catch(error => {
          reject(error);
        });
    });

Magento keeps error text inside data.message, but response.json() return me a Promise instead of data.

What is a correct way to handle this case?

UPDATE response like enter image description here

VLAZ
  • 26,331
  • 9
  • 49
  • 67
Dima Portenko
  • 3,443
  • 5
  • 35
  • 48

2 Answers2

19

You're falling prey to the explicit Promise creation antipattern. You don't need new Promise in that code at all, and to add the status check, simply do it in a then handler:

return fetch(uri, { method, headers, body: JSON.stringify(data) })
    .then(response => {
        if (!response.ok) {
            return response.json()
                .catch(() => {
                    // Couldn't parse the JSON
                    throw new Error(response.status);
                })
                .then(({message}) => {
                    // Got valid JSON with error response, use it
                    throw new Error(message || response.status);
                });
        }
        // Successful response, parse the JSON and return the data
        return response.json();
    });

Now:

  • If an error is returned with valid JSON body, we try to use message from the parsed JSON as the error (rejection), falling back on response.status if there isn't one.
  • If an error is returned by the body isn't valid JSON, we use response.status as the error (rejection)
  • If a success is returned, we return the result of parsing it
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
-1

to get ok on the second then you can use Promise.all instead

fetch(uri, { method, headers, body: JSON.stringify(data) })
        .then(response => {
          return Promise.all([response.json(),response])
        })
        .then(([responseData,response]) => {
          // handle data here
        })

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

mpm
  • 20,148
  • 7
  • 50
  • 55