2

I am issuing two API calls in parallel, asynchronously so I don't lock up the browser , and I am only receiving one callback.

Here is the code

/* Loop runs twice, from 0 to 1 */
for(var AccountIndex in walletForm.masterpublicKey){
    /* Bunch of code, then... */

    /* Construct an API call to Insight */
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "https://insight.bitpay.com/api/addrs/" + stringOfAddresses + "/txs?from=0&to=100", true);
    xhr.onreadystatechange = function() {
        if (xhr.readyState == 4) {
        $scope.$apply(function () {
            txListInsight.txs[AccountIndex] = ( JSON.parse(xhr.responseText));
            /* Set semaphore */
            txListInsight.txsReady[AccountIndex] = true;
            parseTransactions(AccountIndex);
            console.log(txList);
        })
        }
    }
    xhr.send();
}

I can even see the two requests in the Chrome Dev Console Network Tab and the responses are correct. Why am I only getting one callback and not two? Is my second callback overwriting the reference to the first one?

Why is there a library on the Internet called “AsyncXMLHttpRequest”? I am using AngularJS as well--shall I look into "promises"?

Another option would be to avoid the problem entirely by combining my two API requests into one, but I'm not sure what the character limit is.

2
  • what happens if you construct an array of XMLHttpRequest objects, instead of overwriting the callback on each iteration Commented May 23, 2015 at 23:36
  • 1
    This is a classic closure in a loop problem. The variable xhr is closed over and the closure needs to be broken. Commented May 24, 2015 at 10:32

1 Answer 1

1

I think explicitly invoking function with the current AccountIndex should work, notice the closure

var xhrs = {};
for(var AccountIndex in walletForm.masterpublicKey){
    (function(AccountIndex) {

      xhrs[AccountIndex] = new XMLHttpRequest();
      xhrs[AccountIndex].open("GET", "https://insight.bitpay.com/api/addrs/" + stringOfAddresses + "/txs?from=0&to=100", true);
      xhrs[AccountIndex].onreadystatechange = function() {
        if (xhrs[AccountIndex].readyState == 4) {
        $scope.$apply(function () {
            txListInsight.txs[AccountIndex] = ( JSON.parse(xhrs[AccountIndex].responseText));
            /* Set semaphore */
            txListInsight.txsReady[AccountIndex] = true;
            parseTransactions(AccountIndex);
            console.log(txList);
        })
        }
      }
      xhrs[AccountIndex].send();
    })(AccountIndex);
}
Sign up to request clarification or add additional context in comments.

1 Comment

Good idea. I tried it--it gives the same result, only one callback.

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.