fetch: Reject promise with JSON error object












50














I have an HTTP API that returns JSON data both on success and on failure.



An example failure would look like this:



~ ◆ http get http://localhost:5000/api/isbn/2266202022 
HTTP/1.1 400 BAD REQUEST
Content-Length: 171
Content-Type: application/json
Server: TornadoServer/4.0

{
"message": "There was an issue with at least some of the supplied values.",
"payload": {
"isbn": "Could not find match for ISBN."
},
"type": "validation"
}


What I want to achieve in my JavaScript code is something like this:



fetch(url)
.then((resp) => {
if (resp.status >= 200 && resp.status < 300) {
return resp.json();
} else {
// This does not work, since the Promise returned by `json()` is never fulfilled
return Promise.reject(resp.json());
}
})
.catch((error) => {
// Do something with the error object
}









share|improve this question
























  • You mean json method returns a Promise?
    – thefourtheye
    Apr 6 '15 at 14:48






  • 3




    Yes, as per the fetch spec from the working group: fetch.spec.whatwg.org/#concept-body-consume-body
    – jbaiter
    Apr 6 '15 at 15:18
















50














I have an HTTP API that returns JSON data both on success and on failure.



An example failure would look like this:



~ ◆ http get http://localhost:5000/api/isbn/2266202022 
HTTP/1.1 400 BAD REQUEST
Content-Length: 171
Content-Type: application/json
Server: TornadoServer/4.0

{
"message": "There was an issue with at least some of the supplied values.",
"payload": {
"isbn": "Could not find match for ISBN."
},
"type": "validation"
}


What I want to achieve in my JavaScript code is something like this:



fetch(url)
.then((resp) => {
if (resp.status >= 200 && resp.status < 300) {
return resp.json();
} else {
// This does not work, since the Promise returned by `json()` is never fulfilled
return Promise.reject(resp.json());
}
})
.catch((error) => {
// Do something with the error object
}









share|improve this question
























  • You mean json method returns a Promise?
    – thefourtheye
    Apr 6 '15 at 14:48






  • 3




    Yes, as per the fetch spec from the working group: fetch.spec.whatwg.org/#concept-body-consume-body
    – jbaiter
    Apr 6 '15 at 15:18














50












50








50


23





I have an HTTP API that returns JSON data both on success and on failure.



An example failure would look like this:



~ ◆ http get http://localhost:5000/api/isbn/2266202022 
HTTP/1.1 400 BAD REQUEST
Content-Length: 171
Content-Type: application/json
Server: TornadoServer/4.0

{
"message": "There was an issue with at least some of the supplied values.",
"payload": {
"isbn": "Could not find match for ISBN."
},
"type": "validation"
}


What I want to achieve in my JavaScript code is something like this:



fetch(url)
.then((resp) => {
if (resp.status >= 200 && resp.status < 300) {
return resp.json();
} else {
// This does not work, since the Promise returned by `json()` is never fulfilled
return Promise.reject(resp.json());
}
})
.catch((error) => {
// Do something with the error object
}









share|improve this question















I have an HTTP API that returns JSON data both on success and on failure.



An example failure would look like this:



~ ◆ http get http://localhost:5000/api/isbn/2266202022 
HTTP/1.1 400 BAD REQUEST
Content-Length: 171
Content-Type: application/json
Server: TornadoServer/4.0

{
"message": "There was an issue with at least some of the supplied values.",
"payload": {
"isbn": "Could not find match for ISBN."
},
"type": "validation"
}


What I want to achieve in my JavaScript code is something like this:



fetch(url)
.then((resp) => {
if (resp.status >= 200 && resp.status < 300) {
return resp.json();
} else {
// This does not work, since the Promise returned by `json()` is never fulfilled
return Promise.reject(resp.json());
}
})
.catch((error) => {
// Do something with the error object
}






javascript promise es6-promise fetch-api






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Sep 8 '15 at 4:36









sideshowbarker

31k147191




31k147191










asked Apr 6 '15 at 14:38









jbaiterjbaiter

3,49632333




3,49632333












  • You mean json method returns a Promise?
    – thefourtheye
    Apr 6 '15 at 14:48






  • 3




    Yes, as per the fetch spec from the working group: fetch.spec.whatwg.org/#concept-body-consume-body
    – jbaiter
    Apr 6 '15 at 15:18


















  • You mean json method returns a Promise?
    – thefourtheye
    Apr 6 '15 at 14:48






  • 3




    Yes, as per the fetch spec from the working group: fetch.spec.whatwg.org/#concept-body-consume-body
    – jbaiter
    Apr 6 '15 at 15:18
















You mean json method returns a Promise?
– thefourtheye
Apr 6 '15 at 14:48




You mean json method returns a Promise?
– thefourtheye
Apr 6 '15 at 14:48




3




3




Yes, as per the fetch spec from the working group: fetch.spec.whatwg.org/#concept-body-consume-body
– jbaiter
Apr 6 '15 at 15:18




Yes, as per the fetch spec from the working group: fetch.spec.whatwg.org/#concept-body-consume-body
– jbaiter
Apr 6 '15 at 15:18












3 Answers
3






active

oldest

votes


















81















 // This does not work, since the Promise returned by `json()` is never fulfilled
return Promise.reject(resp.json());



Well, the resp.json promise will be fulfilled, only Promise.reject doesn't wait for it and immediately rejects with a promise.



I'll assume that you rather want to do the following:



fetch(url).then((resp) => {
let json = resp.json(); // there's always a body
if (resp.status >= 200 && resp.status < 300) {
return json;
} else {
return json.then(Promise.reject.bind(Promise));
}
})


(or, written explicitly)



    return json.then(err => {throw err;});





share|improve this answer























  • Thanks, that (almost) did work! I had to wrap Promise.reject in an anonymous function or I'd get an undefined is not a function error, but with that small change it works :-)
    – jbaiter
    Apr 7 '15 at 8:10










  • Uh, are you lazy-loading a Promise shim? The native Promise.reject should never be undefined.
    – Bergi
    Apr 7 '15 at 10:09










  • The shim is loaded on application startup, so it shouldn't be lazy-loaded. I can access Promise.reject just fine from the debugger, too. Here's the full trace: TypeError: undefined is not a function {stack: "TypeError: undefined is not a function↵ at reject (native)", message: "undefined is not a function"}
    – jbaiter
    Apr 7 '15 at 11:45








  • 2




    At reject? Ah, it needs to be .then(Promise.reject.bind(Promise)).
    – Bergi
    Apr 7 '15 at 14:00






  • 1




    @torazaburo: No, json is a promise here, and we don't want to reject with the promise but with its result value.
    – Bergi
    Sep 8 '15 at 10:13



















34














Here's a somewhat cleaner approach that relies on response.ok and makes use of the underlying JSON data instead of the Promise returned by .json().






function myFetchWrapper(url) {
return fetch(url).then(response => {
return response.json().then(json => {
return response.ok ? json : Promise.reject(json);
});
});
}

// This should trigger the .then() with the JSON response,
// since the response is an HTTP 200.
myFetchWrapper('http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY').then(console.log.bind(console));

// This should trigger the .catch() with the JSON response,
// since the response is an HTTP 400.
myFetchWrapper('https://content.googleapis.com/youtube/v3/search').catch(console.warn.bind(console));








share|improve this answer

















  • 1




    Ah, .ok looks interesting. Yet I don't see usage of "the underlying JSON data" is cleaner. After all, you could simplify this to fetch(url).then(response => response.ok ? response.json() : response.json().then(err => Promise.reject(err)))
    – Bergi
    Sep 9 '15 at 21:12










  • I meant that instead of let json = resp.json(); where json is a Promise, it could be simpler to resolve the Promise first and then make use of the data its resolved with. Either approach works.
    – Jeff Posnick
    Sep 10 '15 at 13:28










  • Was trying to reject the nested promise but wasn't quite sure how. Turns out it's simply a call to the static "reject" method. A far better answer than the accepted one in my view.
    – Andris
    Apr 1 '16 at 20:06



















2














The solution above from Jeff Posnick is my favourite way of doing it, but the nesting is pretty ugly.



With the newer async/await syntax we can do it in a more synchronous looking way, without the ugly nesting that can quickly become confusing.



async function myFetchWrapper(url) {
const response = await fetch(url);
const json = await response.json();
return response.ok ? json : Promise.reject(json);
}


This works because, an async function always returns a promise and once we have the JSON we can then decide how to return it based on the response status (using response.ok).



You would error handle the same way as you would in Jeff's answer, or you could use try/catch, or even an error handling higher order function.



const url = 'http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY'

// Example with Promises
myFetchWrapper(url)
.then((res) => ...)
.catch((err) => ...);

// Example with try/catch (presuming wrapped in an async function)
try {
const data = await myFetchWrapper(url);
...
} catch (err) {
throw new Error(err.message);
}





share|improve this answer























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f29473426%2ffetch-reject-promise-with-json-error-object%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    3 Answers
    3






    active

    oldest

    votes








    3 Answers
    3






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    81















     // This does not work, since the Promise returned by `json()` is never fulfilled
    return Promise.reject(resp.json());



    Well, the resp.json promise will be fulfilled, only Promise.reject doesn't wait for it and immediately rejects with a promise.



    I'll assume that you rather want to do the following:



    fetch(url).then((resp) => {
    let json = resp.json(); // there's always a body
    if (resp.status >= 200 && resp.status < 300) {
    return json;
    } else {
    return json.then(Promise.reject.bind(Promise));
    }
    })


    (or, written explicitly)



        return json.then(err => {throw err;});





    share|improve this answer























    • Thanks, that (almost) did work! I had to wrap Promise.reject in an anonymous function or I'd get an undefined is not a function error, but with that small change it works :-)
      – jbaiter
      Apr 7 '15 at 8:10










    • Uh, are you lazy-loading a Promise shim? The native Promise.reject should never be undefined.
      – Bergi
      Apr 7 '15 at 10:09










    • The shim is loaded on application startup, so it shouldn't be lazy-loaded. I can access Promise.reject just fine from the debugger, too. Here's the full trace: TypeError: undefined is not a function {stack: "TypeError: undefined is not a function↵ at reject (native)", message: "undefined is not a function"}
      – jbaiter
      Apr 7 '15 at 11:45








    • 2




      At reject? Ah, it needs to be .then(Promise.reject.bind(Promise)).
      – Bergi
      Apr 7 '15 at 14:00






    • 1




      @torazaburo: No, json is a promise here, and we don't want to reject with the promise but with its result value.
      – Bergi
      Sep 8 '15 at 10:13
















    81















     // This does not work, since the Promise returned by `json()` is never fulfilled
    return Promise.reject(resp.json());



    Well, the resp.json promise will be fulfilled, only Promise.reject doesn't wait for it and immediately rejects with a promise.



    I'll assume that you rather want to do the following:



    fetch(url).then((resp) => {
    let json = resp.json(); // there's always a body
    if (resp.status >= 200 && resp.status < 300) {
    return json;
    } else {
    return json.then(Promise.reject.bind(Promise));
    }
    })


    (or, written explicitly)



        return json.then(err => {throw err;});





    share|improve this answer























    • Thanks, that (almost) did work! I had to wrap Promise.reject in an anonymous function or I'd get an undefined is not a function error, but with that small change it works :-)
      – jbaiter
      Apr 7 '15 at 8:10










    • Uh, are you lazy-loading a Promise shim? The native Promise.reject should never be undefined.
      – Bergi
      Apr 7 '15 at 10:09










    • The shim is loaded on application startup, so it shouldn't be lazy-loaded. I can access Promise.reject just fine from the debugger, too. Here's the full trace: TypeError: undefined is not a function {stack: "TypeError: undefined is not a function↵ at reject (native)", message: "undefined is not a function"}
      – jbaiter
      Apr 7 '15 at 11:45








    • 2




      At reject? Ah, it needs to be .then(Promise.reject.bind(Promise)).
      – Bergi
      Apr 7 '15 at 14:00






    • 1




      @torazaburo: No, json is a promise here, and we don't want to reject with the promise but with its result value.
      – Bergi
      Sep 8 '15 at 10:13














    81












    81








    81







     // This does not work, since the Promise returned by `json()` is never fulfilled
    return Promise.reject(resp.json());



    Well, the resp.json promise will be fulfilled, only Promise.reject doesn't wait for it and immediately rejects with a promise.



    I'll assume that you rather want to do the following:



    fetch(url).then((resp) => {
    let json = resp.json(); // there's always a body
    if (resp.status >= 200 && resp.status < 300) {
    return json;
    } else {
    return json.then(Promise.reject.bind(Promise));
    }
    })


    (or, written explicitly)



        return json.then(err => {throw err;});





    share|improve this answer















     // This does not work, since the Promise returned by `json()` is never fulfilled
    return Promise.reject(resp.json());



    Well, the resp.json promise will be fulfilled, only Promise.reject doesn't wait for it and immediately rejects with a promise.



    I'll assume that you rather want to do the following:



    fetch(url).then((resp) => {
    let json = resp.json(); // there's always a body
    if (resp.status >= 200 && resp.status < 300) {
    return json;
    } else {
    return json.then(Promise.reject.bind(Promise));
    }
    })


    (or, written explicitly)



        return json.then(err => {throw err;});






    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Dec 29 '16 at 2:11









    Vladimir Kovpak

    10.6k43646




    10.6k43646










    answered Apr 6 '15 at 16:52









    BergiBergi

    365k58544869




    365k58544869












    • Thanks, that (almost) did work! I had to wrap Promise.reject in an anonymous function or I'd get an undefined is not a function error, but with that small change it works :-)
      – jbaiter
      Apr 7 '15 at 8:10










    • Uh, are you lazy-loading a Promise shim? The native Promise.reject should never be undefined.
      – Bergi
      Apr 7 '15 at 10:09










    • The shim is loaded on application startup, so it shouldn't be lazy-loaded. I can access Promise.reject just fine from the debugger, too. Here's the full trace: TypeError: undefined is not a function {stack: "TypeError: undefined is not a function↵ at reject (native)", message: "undefined is not a function"}
      – jbaiter
      Apr 7 '15 at 11:45








    • 2




      At reject? Ah, it needs to be .then(Promise.reject.bind(Promise)).
      – Bergi
      Apr 7 '15 at 14:00






    • 1




      @torazaburo: No, json is a promise here, and we don't want to reject with the promise but with its result value.
      – Bergi
      Sep 8 '15 at 10:13


















    • Thanks, that (almost) did work! I had to wrap Promise.reject in an anonymous function or I'd get an undefined is not a function error, but with that small change it works :-)
      – jbaiter
      Apr 7 '15 at 8:10










    • Uh, are you lazy-loading a Promise shim? The native Promise.reject should never be undefined.
      – Bergi
      Apr 7 '15 at 10:09










    • The shim is loaded on application startup, so it shouldn't be lazy-loaded. I can access Promise.reject just fine from the debugger, too. Here's the full trace: TypeError: undefined is not a function {stack: "TypeError: undefined is not a function↵ at reject (native)", message: "undefined is not a function"}
      – jbaiter
      Apr 7 '15 at 11:45








    • 2




      At reject? Ah, it needs to be .then(Promise.reject.bind(Promise)).
      – Bergi
      Apr 7 '15 at 14:00






    • 1




      @torazaburo: No, json is a promise here, and we don't want to reject with the promise but with its result value.
      – Bergi
      Sep 8 '15 at 10:13
















    Thanks, that (almost) did work! I had to wrap Promise.reject in an anonymous function or I'd get an undefined is not a function error, but with that small change it works :-)
    – jbaiter
    Apr 7 '15 at 8:10




    Thanks, that (almost) did work! I had to wrap Promise.reject in an anonymous function or I'd get an undefined is not a function error, but with that small change it works :-)
    – jbaiter
    Apr 7 '15 at 8:10












    Uh, are you lazy-loading a Promise shim? The native Promise.reject should never be undefined.
    – Bergi
    Apr 7 '15 at 10:09




    Uh, are you lazy-loading a Promise shim? The native Promise.reject should never be undefined.
    – Bergi
    Apr 7 '15 at 10:09












    The shim is loaded on application startup, so it shouldn't be lazy-loaded. I can access Promise.reject just fine from the debugger, too. Here's the full trace: TypeError: undefined is not a function {stack: "TypeError: undefined is not a function↵ at reject (native)", message: "undefined is not a function"}
    – jbaiter
    Apr 7 '15 at 11:45






    The shim is loaded on application startup, so it shouldn't be lazy-loaded. I can access Promise.reject just fine from the debugger, too. Here's the full trace: TypeError: undefined is not a function {stack: "TypeError: undefined is not a function↵ at reject (native)", message: "undefined is not a function"}
    – jbaiter
    Apr 7 '15 at 11:45






    2




    2




    At reject? Ah, it needs to be .then(Promise.reject.bind(Promise)).
    – Bergi
    Apr 7 '15 at 14:00




    At reject? Ah, it needs to be .then(Promise.reject.bind(Promise)).
    – Bergi
    Apr 7 '15 at 14:00




    1




    1




    @torazaburo: No, json is a promise here, and we don't want to reject with the promise but with its result value.
    – Bergi
    Sep 8 '15 at 10:13




    @torazaburo: No, json is a promise here, and we don't want to reject with the promise but with its result value.
    – Bergi
    Sep 8 '15 at 10:13













    34














    Here's a somewhat cleaner approach that relies on response.ok and makes use of the underlying JSON data instead of the Promise returned by .json().






    function myFetchWrapper(url) {
    return fetch(url).then(response => {
    return response.json().then(json => {
    return response.ok ? json : Promise.reject(json);
    });
    });
    }

    // This should trigger the .then() with the JSON response,
    // since the response is an HTTP 200.
    myFetchWrapper('http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY').then(console.log.bind(console));

    // This should trigger the .catch() with the JSON response,
    // since the response is an HTTP 400.
    myFetchWrapper('https://content.googleapis.com/youtube/v3/search').catch(console.warn.bind(console));








    share|improve this answer

















    • 1




      Ah, .ok looks interesting. Yet I don't see usage of "the underlying JSON data" is cleaner. After all, you could simplify this to fetch(url).then(response => response.ok ? response.json() : response.json().then(err => Promise.reject(err)))
      – Bergi
      Sep 9 '15 at 21:12










    • I meant that instead of let json = resp.json(); where json is a Promise, it could be simpler to resolve the Promise first and then make use of the data its resolved with. Either approach works.
      – Jeff Posnick
      Sep 10 '15 at 13:28










    • Was trying to reject the nested promise but wasn't quite sure how. Turns out it's simply a call to the static "reject" method. A far better answer than the accepted one in my view.
      – Andris
      Apr 1 '16 at 20:06
















    34














    Here's a somewhat cleaner approach that relies on response.ok and makes use of the underlying JSON data instead of the Promise returned by .json().






    function myFetchWrapper(url) {
    return fetch(url).then(response => {
    return response.json().then(json => {
    return response.ok ? json : Promise.reject(json);
    });
    });
    }

    // This should trigger the .then() with the JSON response,
    // since the response is an HTTP 200.
    myFetchWrapper('http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY').then(console.log.bind(console));

    // This should trigger the .catch() with the JSON response,
    // since the response is an HTTP 400.
    myFetchWrapper('https://content.googleapis.com/youtube/v3/search').catch(console.warn.bind(console));








    share|improve this answer

















    • 1




      Ah, .ok looks interesting. Yet I don't see usage of "the underlying JSON data" is cleaner. After all, you could simplify this to fetch(url).then(response => response.ok ? response.json() : response.json().then(err => Promise.reject(err)))
      – Bergi
      Sep 9 '15 at 21:12










    • I meant that instead of let json = resp.json(); where json is a Promise, it could be simpler to resolve the Promise first and then make use of the data its resolved with. Either approach works.
      – Jeff Posnick
      Sep 10 '15 at 13:28










    • Was trying to reject the nested promise but wasn't quite sure how. Turns out it's simply a call to the static "reject" method. A far better answer than the accepted one in my view.
      – Andris
      Apr 1 '16 at 20:06














    34












    34








    34






    Here's a somewhat cleaner approach that relies on response.ok and makes use of the underlying JSON data instead of the Promise returned by .json().






    function myFetchWrapper(url) {
    return fetch(url).then(response => {
    return response.json().then(json => {
    return response.ok ? json : Promise.reject(json);
    });
    });
    }

    // This should trigger the .then() with the JSON response,
    // since the response is an HTTP 200.
    myFetchWrapper('http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY').then(console.log.bind(console));

    // This should trigger the .catch() with the JSON response,
    // since the response is an HTTP 400.
    myFetchWrapper('https://content.googleapis.com/youtube/v3/search').catch(console.warn.bind(console));








    share|improve this answer












    Here's a somewhat cleaner approach that relies on response.ok and makes use of the underlying JSON data instead of the Promise returned by .json().






    function myFetchWrapper(url) {
    return fetch(url).then(response => {
    return response.json().then(json => {
    return response.ok ? json : Promise.reject(json);
    });
    });
    }

    // This should trigger the .then() with the JSON response,
    // since the response is an HTTP 200.
    myFetchWrapper('http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY').then(console.log.bind(console));

    // This should trigger the .catch() with the JSON response,
    // since the response is an HTTP 400.
    myFetchWrapper('https://content.googleapis.com/youtube/v3/search').catch(console.warn.bind(console));








    function myFetchWrapper(url) {
    return fetch(url).then(response => {
    return response.json().then(json => {
    return response.ok ? json : Promise.reject(json);
    });
    });
    }

    // This should trigger the .then() with the JSON response,
    // since the response is an HTTP 200.
    myFetchWrapper('http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY').then(console.log.bind(console));

    // This should trigger the .catch() with the JSON response,
    // since the response is an HTTP 400.
    myFetchWrapper('https://content.googleapis.com/youtube/v3/search').catch(console.warn.bind(console));





    function myFetchWrapper(url) {
    return fetch(url).then(response => {
    return response.json().then(json => {
    return response.ok ? json : Promise.reject(json);
    });
    });
    }

    // This should trigger the .then() with the JSON response,
    // since the response is an HTTP 200.
    myFetchWrapper('http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY').then(console.log.bind(console));

    // This should trigger the .catch() with the JSON response,
    // since the response is an HTTP 400.
    myFetchWrapper('https://content.googleapis.com/youtube/v3/search').catch(console.warn.bind(console));






    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Sep 9 '15 at 20:42









    Jeff PosnickJeff Posnick

    28.9k46092




    28.9k46092








    • 1




      Ah, .ok looks interesting. Yet I don't see usage of "the underlying JSON data" is cleaner. After all, you could simplify this to fetch(url).then(response => response.ok ? response.json() : response.json().then(err => Promise.reject(err)))
      – Bergi
      Sep 9 '15 at 21:12










    • I meant that instead of let json = resp.json(); where json is a Promise, it could be simpler to resolve the Promise first and then make use of the data its resolved with. Either approach works.
      – Jeff Posnick
      Sep 10 '15 at 13:28










    • Was trying to reject the nested promise but wasn't quite sure how. Turns out it's simply a call to the static "reject" method. A far better answer than the accepted one in my view.
      – Andris
      Apr 1 '16 at 20:06














    • 1




      Ah, .ok looks interesting. Yet I don't see usage of "the underlying JSON data" is cleaner. After all, you could simplify this to fetch(url).then(response => response.ok ? response.json() : response.json().then(err => Promise.reject(err)))
      – Bergi
      Sep 9 '15 at 21:12










    • I meant that instead of let json = resp.json(); where json is a Promise, it could be simpler to resolve the Promise first and then make use of the data its resolved with. Either approach works.
      – Jeff Posnick
      Sep 10 '15 at 13:28










    • Was trying to reject the nested promise but wasn't quite sure how. Turns out it's simply a call to the static "reject" method. A far better answer than the accepted one in my view.
      – Andris
      Apr 1 '16 at 20:06








    1




    1




    Ah, .ok looks interesting. Yet I don't see usage of "the underlying JSON data" is cleaner. After all, you could simplify this to fetch(url).then(response => response.ok ? response.json() : response.json().then(err => Promise.reject(err)))
    – Bergi
    Sep 9 '15 at 21:12




    Ah, .ok looks interesting. Yet I don't see usage of "the underlying JSON data" is cleaner. After all, you could simplify this to fetch(url).then(response => response.ok ? response.json() : response.json().then(err => Promise.reject(err)))
    – Bergi
    Sep 9 '15 at 21:12












    I meant that instead of let json = resp.json(); where json is a Promise, it could be simpler to resolve the Promise first and then make use of the data its resolved with. Either approach works.
    – Jeff Posnick
    Sep 10 '15 at 13:28




    I meant that instead of let json = resp.json(); where json is a Promise, it could be simpler to resolve the Promise first and then make use of the data its resolved with. Either approach works.
    – Jeff Posnick
    Sep 10 '15 at 13:28












    Was trying to reject the nested promise but wasn't quite sure how. Turns out it's simply a call to the static "reject" method. A far better answer than the accepted one in my view.
    – Andris
    Apr 1 '16 at 20:06




    Was trying to reject the nested promise but wasn't quite sure how. Turns out it's simply a call to the static "reject" method. A far better answer than the accepted one in my view.
    – Andris
    Apr 1 '16 at 20:06











    2














    The solution above from Jeff Posnick is my favourite way of doing it, but the nesting is pretty ugly.



    With the newer async/await syntax we can do it in a more synchronous looking way, without the ugly nesting that can quickly become confusing.



    async function myFetchWrapper(url) {
    const response = await fetch(url);
    const json = await response.json();
    return response.ok ? json : Promise.reject(json);
    }


    This works because, an async function always returns a promise and once we have the JSON we can then decide how to return it based on the response status (using response.ok).



    You would error handle the same way as you would in Jeff's answer, or you could use try/catch, or even an error handling higher order function.



    const url = 'http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY'

    // Example with Promises
    myFetchWrapper(url)
    .then((res) => ...)
    .catch((err) => ...);

    // Example with try/catch (presuming wrapped in an async function)
    try {
    const data = await myFetchWrapper(url);
    ...
    } catch (err) {
    throw new Error(err.message);
    }





    share|improve this answer




























      2














      The solution above from Jeff Posnick is my favourite way of doing it, but the nesting is pretty ugly.



      With the newer async/await syntax we can do it in a more synchronous looking way, without the ugly nesting that can quickly become confusing.



      async function myFetchWrapper(url) {
      const response = await fetch(url);
      const json = await response.json();
      return response.ok ? json : Promise.reject(json);
      }


      This works because, an async function always returns a promise and once we have the JSON we can then decide how to return it based on the response status (using response.ok).



      You would error handle the same way as you would in Jeff's answer, or you could use try/catch, or even an error handling higher order function.



      const url = 'http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY'

      // Example with Promises
      myFetchWrapper(url)
      .then((res) => ...)
      .catch((err) => ...);

      // Example with try/catch (presuming wrapped in an async function)
      try {
      const data = await myFetchWrapper(url);
      ...
      } catch (err) {
      throw new Error(err.message);
      }





      share|improve this answer


























        2












        2








        2






        The solution above from Jeff Posnick is my favourite way of doing it, but the nesting is pretty ugly.



        With the newer async/await syntax we can do it in a more synchronous looking way, without the ugly nesting that can quickly become confusing.



        async function myFetchWrapper(url) {
        const response = await fetch(url);
        const json = await response.json();
        return response.ok ? json : Promise.reject(json);
        }


        This works because, an async function always returns a promise and once we have the JSON we can then decide how to return it based on the response status (using response.ok).



        You would error handle the same way as you would in Jeff's answer, or you could use try/catch, or even an error handling higher order function.



        const url = 'http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY'

        // Example with Promises
        myFetchWrapper(url)
        .then((res) => ...)
        .catch((err) => ...);

        // Example with try/catch (presuming wrapped in an async function)
        try {
        const data = await myFetchWrapper(url);
        ...
        } catch (err) {
        throw new Error(err.message);
        }





        share|improve this answer














        The solution above from Jeff Posnick is my favourite way of doing it, but the nesting is pretty ugly.



        With the newer async/await syntax we can do it in a more synchronous looking way, without the ugly nesting that can quickly become confusing.



        async function myFetchWrapper(url) {
        const response = await fetch(url);
        const json = await response.json();
        return response.ok ? json : Promise.reject(json);
        }


        This works because, an async function always returns a promise and once we have the JSON we can then decide how to return it based on the response status (using response.ok).



        You would error handle the same way as you would in Jeff's answer, or you could use try/catch, or even an error handling higher order function.



        const url = 'http://api.openweathermap.org/data/2.5/weather?q=Brooklyn,NY'

        // Example with Promises
        myFetchWrapper(url)
        .then((res) => ...)
        .catch((err) => ...);

        // Example with try/catch (presuming wrapped in an async function)
        try {
        const data = await myFetchWrapper(url);
        ...
        } catch (err) {
        throw new Error(err.message);
        }






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 23 '18 at 12:08

























        answered Jun 8 '18 at 11:16









        tomhughestomhughes

        1,2331018




        1,2331018






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f29473426%2ffetch-reject-promise-with-json-error-object%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Trompette piccolo

            How do I get these specific pathlines to nodes?

            What visual should I use to simply compare current year value vs last year in Power BI desktop