1

This is my each loop:-

var image_obj = {};

$(".wrapper").each(function (index, data) {
  var dfile = this.getElementsByClassName('image')[0];
  file = dfile.files[0];
  if(file != null) {
    var fr = new FileReader();


fr.onload = function (e) {

          img = new Image();
          img.onload = function (k) {
            var canvas = document.createElement("canvas");
            canvas.width = img.width;
            canvas.height = img.height;
            var ctx = canvas.getContext("2d");
            ctx.drawImage(img, 0, 0);
            objindex = "obj_" + index;
            image_obj[objindex] = canvas.toDataURL("image/jpeg");

          };
          img.src = fr.result;
        };
        fr.readAsDataURL(file);
      }
    });

I need the index of my each loop to save base_64 encoded image to an object.

But the index is not showing up in order as each loop execution finishes before reaching canvas.getContext("2d");.

Sachin Prasad
  • 5,038
  • 12
  • 49
  • 91
  • possible duplicate of [Whats the smartest / cleanest way to iterate async over arrays (or objs)?](http://stackoverflow.com/questions/8413857/whats-the-smartest-cleanest-way-to-iterate-async-over-arrays-or-objs) – Ryan Lynch May 01 '13 at 07:13

1 Answers1

0

One big problem is that you need to declare img inside your outer function:

$(".wrapper").each(function (index, data) {
  var img;

The reason is that otherwise, img is a global. The img variable captured in your onload function just contains the current value of that global, which is just whatever the most recent each call assigned it to (likely the last wrapper in the jquery object). Then when onload is called, it writes the wrong image into the canvas. By declaring the variable, you ensure that each outer function scope has its very own img variable for your onload functions to capture, which they'll then use when they're actually applied.

Edit If you want to ensure that the outputed order is right, you should just sort it out at the end, since you don't control when onload runs; that's actually the beauty of it. I'd do something like this:

ctx.drawImage(img, 0, 0);
if (typeof(image_obj.images) == "undefined")
  image_obj.images = [];
image_obj.images[index] = canvas.toDataURL("image/jpeg");

Or just make image_obj itself an array and just do:

ctx.drawImage(img, 0, 0);
image_arr[index] = canvas.toDataURL("image/jpeg");

Depending on whether you need the object as a container for other stuff.

Since that's an array, not an object, the images will be in order.

Edit 2

So the problem now is that you get holes in your array if some of the files aren't there. Let's make that not happen:

var index = -1;
$(".wrapper").each(function (_, data) {
  ...
  if(file != null) {
    var fr = new FileReader();
    index++;
    var localIndex = index; //to capture locally

    fr.onload = function (e) {
      ...
      ctx.drawImage(img, 0, 0);
      image_arr[localIndex] = canvas.toDataURL("image/jpeg");
      ..
  • Still the order of index is 0,2,1 where it should be 0,1,2 – Sachin Prasad May 01 '13 at 07:51
  • Sure, because your `onload` calls just run when when they run. You should make `image_obj` an array, and then they'll be in the correct order. I was just focussing on the part where you might not be drawing what you thought you were drawing. I'll edit. –  May 01 '13 at 07:54
  • Yeah I need the order to retrieve them as there are other things associated with each of them. I need to retrieve them in order conbine them with other form fields and then do an ajx call. – Sachin Prasad May 01 '13 at 07:57
  • BTW there is no issue on drawing the issue is with index. – Sachin Prasad May 01 '13 at 07:58
  • If you didn't see an issue drawing the wrong thing, then you just got lucky about the timing. See my edit for the an easy way to order the images; just use an array. –  May 01 '13 at 08:01
  • In fact, I'm pretty sure the `var` thing would have been a nasty bug; are you sure that without it, your URLs aren't all the same? Because that's how the code runs in my head. –  May 01 '13 at 08:06
  • Problem here is that if file == null it will not go inside and my array will get out of order.One more issue is that the execution is not asynchronous. – Sachin Prasad May 01 '13 at 08:07
  • Hmm, right. Increment index inside of that check instead of using the one provided to your `each` callback. –  May 01 '13 at 08:09
  • I tried that one too but it doesn't increment my counter remains 0 all the time. – Sachin Prasad May 01 '13 at 08:10
  • Still the order of index is same 0,2,1 – Sachin Prasad May 01 '13 at 08:26