0

I want to return a fetch promise to upper layer to use, but I found even this fetch promise fail (be catched), upper layer's then still be called. Is it possible "upper layer's then" only be called when fetch success?

export default function request(url, options) {
  .......
  return fetch(url, options)
    .then(checkStatus)
    .then(parseJSON)
    .then(data => {
      // debugPrint("receive response" + JSON.stringify(data));

      if (+data.status.code !== 200) {
        message.error(data.status.message || "please retry");
      }
      return data;
    })
    .catch(err => {
      message.error(err.toString() || "please retry");
      return err;
    });
}

// then I call request this way:
export function userLogin(account) {
  return request(`${domain}/signin/get_accesstoken`, {
    method: "POST"
  }).then(data => {
    // even catch be called, this then still be called. Is it possible only call this then when catch not be called ?

    do something;
    return data;
  });
}

Second edit: I try to return a promise in then, but look like it is not a promise be returned, I don't know why.

export default function request(url, options) {
  .......
  return fetch(url, options)
    .then(checkStatus)
    .then(parseJSON)
    .then(data => {
      // debugPrint("receive response" + JSON.stringify(data));

      if (+data.status.code !== 200) {
        message.error(data.status.message || "please retry");
      }
      return new Promise(resolve=>{
          resolve(data)
      });
    })
    .catch(err => {
      message.error(err.toString() || "please retry");
      return new Promise((resolve, reject)=>{
         reject(err)
      });
    });
}

Edit third:

    export default function request(url, options) {
  .......
  return fetch(url, options)
    .then(checkStatus)
    .then(parseJSON)
    .then(data => {
      // debugPrint("receive response" + JSON.stringify(data));

      if (+data.status.code !== 200) {
        message.error(data.status.message || "please retry");
      }
      return data;
    })
    .catch(err => {
      message.error(err.toString() || "please retry");
      return;
    });
}

    // then I call request this way:
export function userLogin(account) {
  return request(`${domain}/signin/get_accesstoken`, {
    method: "POST"
  }).then(data => {
    // add this
    if (!data) {
      return
     }
    do something;
    return data;
  });
}
Cindy
  • 275
  • 4
  • 18
  • Well, that's just what `catch` does: handle the error and provide a result to the caller. Don't use `catch` if you don't handle (or rethrow) the error. – Bergi Jul 05 '19 at 11:39
  • yes, I understand this is what catch does. but I want to know how to design for this request/response logic. In request function, then will do all check for response, if there have any error in response, will throw an error to catch. for upper layer, just need to take care of success case(then case), and all error handle by request. so is it the only way to use callback in last then of request function? – Cindy Jul 05 '19 at 12:34
  • No, you should not do error handling in `request` only, an error might happen in `userLogin` as well. Of course you can handle them by ignoring them. For the `request` function, you have 3 options when an error happens: a) fulfill the returned promise with a status flag (requires a conditional in the upper layer), b) never resolve the promise (so that the upper layer never knows when the request finished - you don't want that), or c) reject the returned promise. – Bergi Jul 05 '19 at 14:15
  • @Bergi for a) fulfill the returned promise with a status flag, do you mean the way as Edit three? if so I feel a little repetitive, since I have to add if (!data) in every upper layer functions. and for c) reject the returned promise, I am not understand, I am new in JS area. Possible give some code? Thanks. – Cindy Jul 06 '19 at 01:01
  • Yes, I wouldn't use a) either - better use the promise functionality to signal failure. and the way to do that is c), like the code in your second edit or in Usama's answer, where you rethrow the error. – Bergi Jul 06 '19 at 09:27

1 Answers1

0

if you want to call your upper layer's then only in case of success then throw some error in catch block of fetch instead of returning err.

export default function request(url, options) {
  .......
  return fetch(url, options)
    .then(checkStatus)
    .then(parseJSON)
    .then(data => {
      // debugPrint("receive response" + JSON.stringify(data));

      if (+data.status.code !== 200) {
        message.error(data.status.message || "please retry");
      }
      return data;
    })
    .catch(err => {
      message.error(err.toString() || "please retry");
      throw new Error('fetch failed');     // throw error 
    });
}
Usama Tahir
  • 1,707
  • 3
  • 15
  • 30
  • No, system will say "request.js:62 Uncaught (in promise) Error: fetch failed", I don't want to handle error again in upper layer, since request has handle it. – Cindy Jul 05 '19 at 10:24
  • @Cindy No, you didn't handle the error, you just returned it, and that's why then is triggered in the first place, it thinks the returned error is valid data. So like Usama said you have to rethrow the error – Youssef BH Jul 05 '19 at 11:39
  • if not return in catch, the upper layer then still be called after catch – Cindy Jul 05 '19 at 12:35
  • if you won't return anything from `catch` block then `upper layer's` `catch` block won't get called. – Usama Tahir Jul 05 '19 at 12:40