0

In this case I fetch review data from inside a 'for loop' as you can see here:

fetch('https://api.yotpo.com/products/xx-apikey-xx/{{product.id}}/bottomline')

As not all of the products have reviews, and thus not available which gives a 404 response back for that products. This gives me a lot of errors in the console because the specific id doesn't exist (getElementById ...).

                <script>
                fetch('https://api.yotpo.com/products/xx-apikey-xx/{{product.id}}/bottomline').then(function (response) {
                    if (response.ok) return response.json();
                }).then(function (obj) {
                    var averageScore = (obj).response.bottomline.average_score;
                    var averageTen = averageScore * 2;
                    var averageOverlay = 100 - averageScore * 20;
                    var reviewCount = (obj).response.bottomline.total_reviews;
                    var reviewCountText = "reviews";
                    console.log(obj);
                    document.getElementById("jsonproductreviewcount-{{ product.id }}").innerHTML = "<span class='reviewCount d-flex'>" + reviewCount + " " + reviewCountText + "</span>";
                    document.getElementById("sterrenOverlay-{{ product.id }}").style.width = averageOverlay + "%";
                }).catch(function (error) {
                    console.error('Oops! Errrrrorrr...');
                    console.error(error);
                })
                </script>

Should I use some IF / ELSE statement to check if the productid / response gives a 200 code? But how?

Sunderam Dubey
  • 1
  • 11
  • 20
  • 40
Hielke
  • 169
  • 2
  • 11

1 Answers1

0

Although the people who created fetch apparently disagree, to my mind a non-success response is an error, so I always treat it as one; see ***:

fetch('https://api.yotpo.com/products/xx-apikey-xx/{{product.id}}/bottomline')
.then(function (response) {
    if (!response.ok) {                                   // ***
        throw new Error(`HTTP error ${response.status}`); // ***
    }                                                     // ***
    return response.json();
})
.then(function (obj) {
    var averageScore = (obj).response.bottomline.average_score;
    var averageTen = averageScore * 2;
    var averageOverlay = 100 - averageScore * 20;
    var reviewCount = (obj).response.bottomline.total_reviews;
    var reviewCountText = "reviews";
    console.log(obj);
    document.getElementById("jsonproductreviewcount-{{ product.id }}").innerHTML = "<span class='reviewCount d-flex'>" + reviewCount + " " + reviewCountText + "</span>";
    document.getElementById("sterrenOverlay-{{ product.id }}").style.width = averageOverlay + "%";
})
.catch(function (error) {
    console.error('Oops! Errrrrorrr...');
    console.error(error);
});

That will transfer control from your first then callback to your catch callback.


A couple of side notes:

  • There's no reason for (obj).xyz, just use obj.xyz.
  • var is effectively deprecated; new code should be written with let and/or const.
  • You might consider lighter-weight arrow functions rather than traditional functions.
  • If you can in your target environment (and it's nearly all of them now), you might consider using async/await rather than explicit promise callback functions.

For what it's worth:

fetch("https://api.yotpo.com/products/xx-apikey-xx/{{product.id}}/bottomline")
.then((response) => {
    if (!response.ok) {                                   // ***
        throw new Error(`HTTP error ${response.status}`); // ***
    }                                                     // ***
    return response.json();
})
.then((obj) => {
    const { average_score, total_reviews } = obj.response.bottomline;
    const averageTen = average_score * 2;
    const averageOverlay = 100 - average_score * 20;
    const reviewCountText = "reviews";
    console.log(obj);
    document.getElementById("jsonproductreviewcount-{{ product.id }}").innerHTML =
        `<span class="reviewCount d-flex">${total_reviews} ${reviewCountText}</span>`;
    document.getElementById("sterrenOverlay-{{ product.id }}").style.width = averageOverlay + "%";
})
.catch((error) => {
    console.error("Oops! Errrrrorrr...");
    console.error(error);
});
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thank you very much @T.J. Crowder! I updated my code locally :-) But this doesn't solve my problem. Maybe I wasn't clear enough. When a product doesn't have a review at 3rd party, the product itself gives a 404 and must prevent executing the rest of the script and thus avoid the 404 error. The loop contains products in our shop, but due to no reviews, it's not available for calling through the 3rd party API. Again: many thanks for thinking with me! – Hielke May 11 '22 at 13:54
  • @Hielke - With the above, a 404 will skip all the intervening things and go to the `catch`. Is that not what you want? – T.J. Crowder May 11 '22 at 14:06
  • maybe I'm way too dumb to dive into this stuff :-D I need to get rid off the 404 console errors. Everything works, but when a product doesn't have a review, the endpoint doesn't exist, so it's some kind of 'OK' to throw in a 404 error. Is there a way to ignore the 'loose / not existing' endpoints which are generating the 404 errors? – Hielke May 23 '22 at 14:36
  • @Hielke - If you do the request to the endpoint, I don't think there's a way to get Chrome (etc.) not to log a 404 to the console (without changing the console settings on the browser, which obviously you can't do on your user's machines). More [here](https://stackoverflow.com/questions/9893886/prevent-image-load-errors-going-to-the-javascript-console). – T.J. Crowder May 23 '22 at 14:52