1

I have this multiple function called checkForURLS that calls another two functions that return callbacks, how can I add to the array once both callbacks have returned and then return the array as a callback? I'm working with pure JavaScript.

function checkForURLs(uniqueURL, customURL, callback) {
    var errors = [];

    checkForUniqueURL(uniqueURL, function(UniqueURLCallback) {
        if (UniqueURLCallback===true) {
            errors.push("This unique URL is already taken, please try another.");
        }
    });

    if (customURL.length>0) {
        checkForCustomURL(customURL, function(customURLCallback) {
            if (customURLCallback===true) {
                errors.push("This custom URL is already taken, please try another.");
            }
        });
    }

    if (errors.length>0) {
        return callback(errors);
    } else {
        return callback(false);
    }
}
3
  • Your code should be working. You call checkForURLs(urlA, urlB, function(error) { /* handle your error in the callback function */ });. Isn't that, what you want? What do you want? Commented Oct 23, 2016 at 22:48
  • It seems to be coming back empty, but if I put a callback in one of the inner callbacks to return the callback(errors), it works but just for that particular callback. What's happening is the if statement isn't waiting and just returning instantly. With jQuery I could have used something like 'done' and then returned but not sure how to in JavaScript. Commented Oct 23, 2016 at 22:51
  • 1
    sounds like checkForUniqueURL() does something asynchronous and all this should be done using promises. Show all relevant code Commented Oct 23, 2016 at 22:54

3 Answers 3

1

You can use Promise constructor new Promise(function), Promise.all() to perform task when checkForUniqueURL and checkForCustomURL callbacks have been called.

function callback(value) {
  return value
}

function checkForUniqueURL(url, callback) {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve(callback(true))
    }, Math.random() * 1500)
  })
}

function checkForCustomURL(url, callback) {
  return new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve(callback(true))
    }, Math.random() * 1500)
  })
}

function checkForURLs(uniqueURL, customURL, callback) {
  var errors = [];

  return Promise.all([
    new Promise(function(resolve, reject) {
      checkForUniqueURL(uniqueURL, function(UniqueURLCallback) {
        if (UniqueURLCallback === true) {
          errors.push("This unique URL is already taken, please try another.");
        } 
        resolve()
      })
    })
  , new Promise(function(resolve, reject) {
      if (customURL.length > 0) {
        checkForCustomURL(customURL, function(customURLCallback) {
          if (customURLCallback === true) {
            errors.push("This custom URL is already taken, please try another.");
          }
          resolve()
        });
      }
    })
  ])
  .then(function() {
    console.log(errors);
    if (errors.length > 0) {
        return Promise.resolve(callback(errors));
    } else {
        return Promise.reject(callback(new Error("false")));
    }
  })
}

checkForURLs("abc", "def", callback)
  .then(function(errs) {
    console.log(errs);
  })
  .catch(function(err) {
    console.log("err:", err.message)
  })

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

1 Comment

@PaulNess See updated post. Adjusted resolve() to outside of if`` statement. Previously, if errors.length > 0` was false reject() would not be called.
0

If all functions you use are synchronous and are implemented similar to the following, you code works perfectly well:

function checkForURLs(uniqueURL, customURL, callback) {
    var errors = [];

    checkForUniqueURL(uniqueURL, function(UniqueURLCallback) {
        if (UniqueURLCallback===true) {
            errors.push("This unique URL is already taken, please try another.");
        }
    });

    if (customURL.length>0) {
        checkForCustomURL(customURL, function(customURLCallback) {
            if (customURLCallback===true) {
                errors.push("This custom URL is already taken, please try another.");
            }
        });
    }

    if (errors.length>0) {
        return callback(errors);
    } else {
        return callback(false);
    }
}

// Just test-implement those two functions:
function checkForUniqueURL(url, callback) { callback(true); }
function checkForCustomURL(url, callback) { callback(true); }


errors = checkForURLs("test", "test2", function(errors) {
  console.log(errors);
  return "I have got some errors!";
});

console.log(errors);

If indeed your code has asynchronous parts, you would need to "wait" with the return callback() until those are finished. Maybe by wrapping them in another callback?

Comments

0

This will work IFF your checkForUniqueURL and checkForCustomURL functions are synchronous. Here is an example of it working with synchronous functions...

https://jsfiddle.net/ojh5b1f8/

However, I'm going to assume, since its not working, that your functions are asynchronous. Here is an example of it not working with asynchronous functions...

https://jsfiddle.net/uzjbyrt7/

It doesn't work, because the checkForURLs function returns before the callbacks are fired. The best solution in this case, is Promises. However, you will likely need to use a library to get promise support, since they are not yet implemented in all browsers. I recommend bluebird.js. Here is an example of it working with asynchronous functions and promises...

https://jsfiddle.net/ynxcu7t6/

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.