Вопрос

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>");


                    });



}
Это было полезно?

Решение

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".

Другие советы

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>");


        });
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top