Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>AFAICT, there are two answers to be given here: the one you're asking for, and the one you need. I'll give both in case someone else stumbles upon this answer from Google.</p> <p><strong>What you should do</strong></p> <p>It looks like you're trying to make a bunch of asynchronous calls happen in sequence, and guessing that they'll come back in about three seconds. Of course, if that turns out not to be an accurate guess, you're going to have problems, so what you really want is a function that will be triggered at the instant that the request comes back.</p> <p>There are two ways to do this - either continuation-passing style (aka callback hell), or with promises. The former is easier conceptually, but gets ugly in a hurry:</p> <pre><code>$http('url', function (data) { //this function is called when the AJAX request comes back //do something with data $http('url2', function (data) { //do something with second piece of data after request 2 loads }) }) </code></pre> <p>This gets to be a real mess when you need an arbitrary number. My preferred solution is a recursive higher-order function, such as the following, although it is possible to do it iteratively:</p> <pre><code>var launch = function f (i) { return function (data) { //do something with data if (i &lt;= urls.length - 1) $http(urls[i+1], f(i+1)) } } //manually trigger the first one launch(0)() </code></pre> <p>The cleaner way is with promises. There are hundreds of tutorials on how to use promises to clean up async code, and <a href="https://stackoverflow.com/questions/17757654/how-to-chain-a-variable-number-of-promises-in-q-in-order">here</a> is an example of how to do it for a variable number of requests.</p> <p><strong>What you asked</strong></p> <p>If you really want to just launch a bunch of timeouts with different arguments, the trick is to close over each one to cache the value of <code>i</code>. If you do this:</p> <pre><code>for (var i = 0; i &lt; 20; i++) { setTimeout(function () { //i is 20 by the time this runs... }, 1000) } </code></pre> <p>then all 20 invocations of the function will see <code>i</code> as 20, which is probably not what you wanted.</p> <p>The solution is this:</p> <pre><code>for (var i = 0; i &lt; 20; i++) { setTimeout((function (j) { //do something with j, which is a copy of the value of i for this iteration })(i), 1000) } </code></pre> <p>The reason this works is that explicitly-passed primitive function arguments (i.e. numbers) are passed by value, while "passing" a variable by closure (which is what's happening in the broken example) passes by reference, even for primitives.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload