簡體   English   中英

JavaScript for循環,等待函數回調

[英]Javascript for loop, wait for function callback

我有一個for循環,它本身調用一個函數。 該函數具有一個回調,但是for循環不會等待其完成並繼續工作。

for循環實際上是如此快地完成,以至於在第一個函數調用完成之前完成了下一個要在for循環中填充的文檔的操作。

這是我實際使用的呼叫的內容,其中images是一個包含圖像外部URL的數組:

// New jsPDF Document
var doc = new jsPDF();

doc.setFontSize(12);

// For each image we add the image to the document as an image
for (var index = 0; index < images.length; index++) {

    // We only add pages after the first one
    if (index !== 0) {
        doc.addPage();
    }

    // This puts the URL of the active element at the top of the document
    doc.text(35, 25, images[index].path);

    // Call to our function, this is the 'skipped' portion
    convertImgToDataURLviaCanvas(images[index].path, function(base64Img) {
        console.log('An image was processed');
        doc.addImage(base64Img, 15, 40, 180, 180);
    });
}

doc.save('demo.pdf');
console.log('Document served!');

我們從數組中獲取圖像URL,然后添加所有內容。 convertImgToDataURLviaCanvas函數在此處:

// Gets an URL and gives you a Base 64 Data URL
function convertImgToDataURLviaCanvas(url, callback, outputFormat){
    var img = new Image();
    img.crossOrigin = 'Anonymous';
    img.onload = function() {
        var canvas = document.createElement('CANVAS');
        var ctx = canvas.getContext('2d');
        var dataURL;
        canvas.height = this.height;
        canvas.width = this.width;
        ctx.drawImage(this, 0, 0);
        dataURL = canvas.toDataURL(outputFormat);
        callback(dataURL);
        canvas = null; 
    };
    img.src = url;
}

在前面的示例中,甚至行doc.text(35, 25, images[index].path); 確實將網址寫到頁面頂部。 因為那包含在數組中並且沿着迭代器工作。 但是,在將第一個圖像添加到我們的文檔之前,for循環已完全完成!

使用console.log您將看到: 'Document served!' 在第一個'An image was processed' 我們的目標是將其反轉,在Document served!之前輸出每個'An image was processed' Document served! 出現了。

如何實現此功能?

為了保證圖像的順序,使用諾言很簡單

var promises = images.map(function(image, index) {
    return new Promise(function(resolve) {
        convertImgToDataURLviaCanvas(image.path, function(base64Img) {
            resolve(base64Img);
        });
    });
}
Promise.all(promises).then(function(results) {
    results.forEach(function(base64Img, index) {
        if (index !== 0) {
            doc.addPage();
        }
        doc.text(35, 25, images[index].path);
        console.log('An image was processed');
        doc.addImage(base64Img, 15, 40, 180, 180);
    });
    doc.save('demo.pdf');
    console.log('Document served!');
});

為了完整性(盡管未選中)-保證圖像順序並在正確位置放置addPage / text的非承諾方式

var base64 = new Array(images.length); // base64 images held here
images.forEach(function(image, index) {
    // Call to our function, this is the 'skipped' portion
    convertImgToDataURLviaCanvas(image.path, function(base64Img) {
        console.log('An image was processed');
        // We only add pages after the first one
        base64[index] = base64Img;
        done++;
        if (done == images.length) {
            base64.forEach(function(img64, indx) {
                if (indx !== 0) {
                    doc.addPage();
                }
                // This puts the URL of the active element at the top of the document
                doc.text(35, 25, images[indx].path);
                doc.addImage(img64, 15, 40, 180, 180);
            }
            doc.save('demo.pdf');
            console.log('Document served!');
        }
    });
}

一種方法如下

 
 
 
  
  var done = 0; // added this to keep counf of finished images for (var index = 0; index < images.length; index++) { // We only add pages after the first one if (index !== 0) { doc.addPage(); } // This puts the URL of the active element at the top of the document doc.text(35, 25, images[index].path); // Call to our function, this is the 'skipped' portion convertImgToDataURLviaCanvas(images[index].path, function(base64Img) { console.log('An image was processed'); doc.addImage(base64Img, 15, 40, 180, 180); // added this code, checks number of finished images and finalises the doc when done == images.length done++; if (done == images.length) { // move the doc.save here doc.save('demo.pdf'); console.log('Document served!'); } // end of new code }); }
 
  

使用諾言,很容易...

 
 
 
  
  // For each image we add the image to the document as an image var promises = images.map(function(image, index) { // We only add pages after the first one if (index !== 0) { doc.addPage(); } // This puts the URL of the active element at the top of the document doc.text(35, 25, image.path); // Call to our function, this is the 'skipped' portion // this returns a Promise that is resolved in the callback return new Promise(function(resolve) { convertImgToDataURLviaCanvas(image.path, function(base64Img) { console.log('An image was processed'); doc.addImage(base64Img, 15, 40, 180, 180); resolve(index); // doesn't really matter what is resolved }); }); } Promise.all(promises).then(function(results) { doc.save('demo.pdf'); console.log('Document served!'); });
 
  

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM