Javascript用于循环,等待函数回调
我有一个for循环,它调用自身内部的函数。该函数有一个回调,但是for循环不会等待它完成并继续工作 for循环实际上完成得如此之快,以至于下一个操作(服务于应该在for循环中填充的文档)在第一个函数调用完成之前完成 下面是我实际使用的调用的内容,其中images是一个数组,包含指向图像的外部URL:Javascript用于循环,等待函数回调,javascript,jquery,asynchronous,Javascript,Jquery,Asynchronous,我有一个for循环,它调用自身内部的函数。该函数有一个回调,但是for循环不会等待它完成并继续工作 for循环实际上完成得如此之快,以至于下一个操作(服务于应该在for循环中填充的文档)在第一个函数调用完成之前完成 下面是我实际使用的调用的内容,其中images是一个数组,包含指向图像的外部URL: // New jsPDF Document var doc = new jsPDF(); doc.setFontSize(12); // For each image we add the im
// 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!');
在前面的示例中,甚至行doc.text(35,25,images[index].path)
正确地将URL写入页面顶部。因为它包含在数组中,并沿着迭代器工作。然而,for循环在第一个图像添加到文档之前就已经完成了
使用console.log
您将看到:'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/文本放在正确位置的非承诺方式
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
});
}
到保证图像的顺序,使用承诺很简单
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/文本放在正确位置的非承诺方式
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
});
}
预期结果将等待doc.addPage()
要在调用convertimgtodautaurliviacanvas
之前完成,请执行其回调doc.addPage();预期结果是确保按顺序调用convertimgtodautaurliviacanvas
然后,也只有在那时,让下一个循环迭代开始。这不是一个完整的解决方案,只是检查一下:您是否尝试将doc.save()
部分放入for循环下的convertimgtodautaurliviacanvas
的回调中?doc.addPage()
是convertimgtodautaurliviacanvas
的回调<首先调用code>convertimgtodautauralviacanvas
,然后调用doc.addPage()
?“使用console.log,您将看到第一个‘处理了图像’之前的‘已送达文档’”console.log(‘已送达文档’)代码>是synchronous@guest271314是的,具体地说,doc.addPage()
位于回调内部<代码>convertimgtodautaurlviacanvas(图像[索引]。路径,函数(base64Img){'这是回调'})代码>@alix,这将尝试保存文件的次数。我认为最后一次回调实际上是正确的文件,但我认为这种方式不会导致正确的解决方案
要在调用convertimgtodautaurliviacanvas
之前完成,请执行其回调doc.addPage();预期结果是确保按顺序调用convertimgtodautaurliviacanvas
然后,也只有在那时,让下一个循环迭代开始。这不是一个完整的解决方案,只是检查一下:您是否尝试将doc.save()
部分放入for循环下的convertimgtodautaurliviacanvas
的回调中?doc.addPage()
是convertimgtodautaurliviacanvas
的回调<首先调用code>convertimgtodautauralviacanvas
,然后调用doc.addPage()
?“使用console.log,您将看到第一个‘处理了图像’之前的‘已送达文档’”console.log(‘已送达文档’)代码>是synchronous@guest271314是的,具体地说,doc.addPage()
位于回调内部<代码>convertimgtodautaurlviacanvas(图像[索引]。路径,函数(base64Img){'这是回调'})代码>@alix,这将尝试保存文件的次数。我想最后一次回调实际上是正确的文件,但我不认为这样就可以找到正确的解决方案。太好了!给我一点时间来测试一下。问题是关于doc.save
调用得太早-任何对wheredoc.addPage
逻辑的重写都应该是无关的,超出了问题的范围。就我而言,Dayeah,我还在@JaromandaX检查它,addPage和doc.text确实需要添加到回调中,否则首先会添加所有页面。如果您愿意使用承诺,以正确的顺序添加图像非常容易-请参见编辑answer@Erick-我添加了一个非承诺保证订单答案-我可以编辑答案,只包括最后两个版本,这两个版本应解决所有问题,即使是问题中最初未提及的问题!给我一点时间来测试一下。问题是关于doc.save
调用得太早-任何对wheredoc.addPage
逻辑的重写都应该是无关的,超出了问题的范围。就我而言,Dayeah,我还在@JaromandaX检查它,addPage和doc.text确实需要添加到回调中,否则首先会添加所有页面。如果您愿意使用承诺,以正确的顺序添加图像非常容易-请参见编辑answer@Erick-我添加了一个非承诺保证订单答案-我可以编辑答案,只包括最后两个版本,这两个版本应解决所有问题,即使是问题中最初未提及的问题