Question

I am trying to loop through an json array of images, adding the images to a marker on map. As javascript is asynchronous it is causing me problems, I want to wait for the image to load before adding it to my map and cannot get my images to load before the loop finishes. Is this possible to achieve as I have tried to implement with callbacks but could not get this to work.

 for (var i = 0; i < jsonObj.potholes.length; i++)
 {  
      var image = new Image();



                image.src = "data:image/png;base64," + jsonObj.potholes[i].image;
                image.onload = function()
                {
                    //alert("image loaded");
                    EXIF.getData(image, function()
                    {
                        otn = parseInt(EXIF.getTag(image, "Orientation"));
                        dataURL = drawCanvas(otn, image).toDataURL();

                        var circle = L.circle([jsonObj.potholes[i].lat, jsonObj.potholes[i].lon], 18, {
                            color: 'yellow',
                            fillColor: 'red',
                            fillOpacity: 0.5
                        }).addTo(markersLayerGroup).bindPopup("Pothole ID " + jsonObj.potholes[i].id
                                + "<br />Location " + city[i] + "," + street[i] +
                                "<image src = '" + dataURL + "'></image>");


                    });



}
Was it helpful?

Solution

You should implement an asynchronous loop (using if):

(function (ondone) {
    var index = 0;
    nextStep();

    function nextStep() {
        if (index >= jsonObj.potholes.length) {
            if (ondone)
                ondone();
            return;
        }

        var i = index++;
        var image = new Image();

        image.src = "data:image/png;base64," + jsonObj.potholes[i].image;
        image.onload = function () {
            //alert("image loaded");
            EXIF.getData(image, function () {
                otn = parseInt(EXIF.getTag(image, "Orientation"));
                dataURL = drawCanvas(otn, image).toDataURL();

                var circle = L.circle([jsonObj.potholes[i].lat, jsonObj.potholes[i].lon], 18, {
                    color: 'yellow',
                    fillColor: 'red',
                    fillOpacity: 0.5
                }).addTo(markersLayerGroup).bindPopup("Pothole ID " + jsonObj.potholes[i].id
                        + "<br />Location " + city[i] + "," + street[i] +
                        "<image src = '" + dataURL + "'></image>");

                nextStep();
            });
        }
    }
})(function () { alert("Done!"); });

You could also use Promises for that, for example: JavaScript: Async Promise "while loop".

OTHER TIPS

Hope it's not too late. There's another much simpler solution--Throw everything into another function.

for (var i = 0; i < jsonObj.potholes.length; i++) {  
    dataOnLoad("data:image/png;base64," + jsonObj.potholes[i].image);
}
function dataOnLoad(base64_data) {
    var image = new Image();
    image.src = base64_data;
    image.onload = function()
    {
        //alert("image loaded");
        EXIF.getData(image, function()
        {
            otn = parseInt(EXIF.getTag(image, "Orientation"));
            dataURL = drawCanvas(otn, image).toDataURL();

            var circle = L.circle([jsonObj.potholes[i].lat, jsonObj.potholes[i].lon], 18, {
                color: 'yellow',
                fillColor: 'red',
                fillOpacity: 0.5
            }).addTo(markersLayerGroup).bindPopup("Pothole ID " + jsonObj.potholes[i].id
                    + "<br />Location " + city[i] + "," + street[i] +
                    "<image src = '" + dataURL + "'></image>");


        });
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top