2

I am just learning about callbacks in javascript and wanted some help with the following code:

(please read entire post: I realise that exists is not set).

       window.addEventListener('load', function(){

    for (let count = 1; count <= 10; count++) {
        var toTest = "pic" + count + "a.jpg";
        var exists;
       imageExists(toTest, function(response){ if(response == true){ console.log("true" + count); exists = true;  } else { console.log("false" + count );  exists = false;}});
       console.log(exists);

       if(!exists){break;}

    }
    });

function imageExists(image_url, callback){
    console.log("processing: " + image_url);
    var http = new XMLHttpRequest();

        http.open('HEAD', image_url, true);
        http.send();
        http.onload = function() {
            console.log(http.status);
            if (http.status != 404)  {
                console.log(image_url + " exists (in imageExists)");
                callback(true);
            } else {
                console.error(image_url + "does not exist (in imageExists)");
                callback(false);
            }
        }

    }

Of course this doesn't work because it is checking exists variable before the callback. I tried replacing exists = false; with break but this this was illegal.

Any solutions to get the callback out of the function without completely changing the code?

Console log is:

processing: pic1a.jpg
app.js:14 undefined
app.js:56 200
app.js:58 pic1a.jpg exists (in imageExists)
app.js:13 true1
2
  • Possible duplicate of Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference Commented Mar 23, 2018 at 2:30
  • 2
    My suggestion is to learn how to express yourself in a purely functional world, rather than this quasi-functional, quasi-procedural world which you seem trapped in. It's easier to convert functional code to procedural code than it is to convert procedural code to functional code (essentially what you're going to be doing)... It's just easier to refactor in functional form. To reiterate: You likely shouldn't use break because break is a procedural idiom which can't elegantly extend its effects beyond the functional idiom you've used here. Commented Mar 23, 2018 at 2:51

4 Answers 4

1

This is a pretty common case that we should use promise and async/await for. This approach is also the way that takes the smallest effort in terms of refactoring your existing code. You can turn imageExists() into a function that returns a promise object, then it'll be able to be used as:

result = await imageExists(imgUrl);

instead of:

imageExists(imgUrl, callback(result) => {...});

Want to learn more advanced skills, please check out ReactiveX libray.

Sign up to request clarification or add additional context in comments.

Comments

0

A simple enough solution would be to convert the listener to an async function, convert imageExists into a Promise, and await it:

window.addEventListener('load', async function() {
  for (let count = 1; count <= 10; count++) {
    const toTest = "pic" + count + "a.jpg";
    const response = await imageExists(toTest);
    const exists = response.ok;
    if (!exists) {
      console.log('does not exist');
      break;
    }
  }
}

function imageExists(image_url) {
  console.log("processing: " + image_url);
  return fetch(image_url, { method: 'HEAD' });
}

1 Comment

Thank you. I see "await" and "promise" a few topics down in my tutorial. I guess I jumped the gun trying to do this without knowing them.
0

so, I think:

function imageExists(image_url, callback) {
    console.log("processing: " + image_url);
    var img = document.createElement("IMG");
    img.load = function() { callback(true); };
    img.error = function() { callback(false); };
    img.src = image_url;
    }

Comments

0

You're mixing synchronous/asynchronous code. You'll want to perform the looping logic with recursion. For example:

function imageExists(a,b){
    if(a>b){
        //found all images, we're done
        return;
    }else{
        var image_url = "pic"+a+"a.jpg";
        console.log("processing: " + image_url);
        var http = new XMLHttpRequest();
        http.open('HEAD', image_url, true);
        http.send();
        http.onload = function() {
            console.log(http.status);
            if (http.status != 404)  {
                console.log(image_url + " exists (in imageExists)");
                //image exists, let's check the next one...
                imageExists(a+1,b)
            } else {
                console.error(image_url + "does not exist (in imageExists)");
                //couldn't find image, stopping early (break)
                return;
            }
        }
    }
}

To check the existence of images 1-10 you'd simply call imageExists(1,10)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.