Q:

Promises within while loop

I'd like to know the reason of the behavior I'm getting with some promises within a while loop.
I had this code so it should run each promise only after the previous promise is resolved. So when I started this task I wrote something like this:
while (i <= totalImages) {
   if (previousDeferred === null) {
     previousDeferred = prepare(i);
   }
   else {
     previousDeferred = previousDeferred.then(prepare(i));
   }
   // code to calculate i value
}

Note that my prepare function returns a promise that is resolved when the image has been loaded and some other logic is executed. But I noticed my code was only waiting for the first promise to be resolved and then all the next images were downloaded immediately.
I changed my code and I wrote the prepareImage function to separate the logic, so there I'm receiving the index to be downloaded and I've the same logic I had within the while loop.
function prepareImage(i) {
    if (previousDeferred === null) {
        previousDeferred = prepare(i);
    }
    else {
        previousDeferred = previousDeferred.then(function(){
            return prepare(i); 
        });
    }
}

while (i <= totalImages) {
    tryToPrepare(paths[i]);
   // code to calculate i value
}

So this is working properly, but I don't know the reason the first code didn't work and the second one worked properly, I think it is something related with the value of i, maybe js creates the chaining when i use the wrapper function since it keeps its value, and avoids the chaining when it knows it changed due to the loop but I'm not pretty sure.
Can somebody help me to understand it?

A:

In the first one this line of code:
previousDeferred = previousDeferred.then(prepare(i));

is calling prepare(i) too soon.  .then() wants you to pass it a function reference that the .then() infrastructure can call sometime later.  But, the way you have it structured above, you are calling prepare(i) immediately and passing that return value to .then().  That's not what you want.
Your second version:
previousDeferred = previousDeferred.then(function(){
    return prepare(i); 
});

is properly passing a function reference so prepare(i) can be called later by the promise infrastructure.  I note that you also made a separate change in the second one with the wrapper function to properly encapsulate the value if i so it didn't change before prepare(i) was called.  That was also necessary to make this version work.
FYI, you could also use .bind() for a shortcut:
previousDeferred = previousDeferred.then(prepare.bind(null, i));

This creates a temporary function that will call prepare(i) when it is later called.  Doing it this way  will not require the wrapper function because the value of i is grabbed at the right time and saved in the bound function for later use.  

