我正在使用JavaScript处理图像。对于每个图像,我使用.toblob创建4个文件。问题在于.toblob是异步的,这样一个.toblob进程可以在其他进程完成时运行。await异步似乎不起作用。处理的图像数的计数器似乎不起作用,因为上一个图像可以处理,而前一个图像尚未完成。最后一个图像将计数器增加到图像数并触发保存。
我可以在最后一个图像上做一个setTimeout,但那只是在猜测最大时间。
代码如下:
let kpData;
let repositoryData;
let collection;
let skuString = `,`;
let numImages;
let numImagesProcessed;
$(document).on(`click`, `.saveSkuImages`, function() {
numImagesProcessed = 0;
kpData = new FormData();
repositoryData = new FormData();
skuString = `,`;
const skuContainer = $(this).closest(`.skuContainer`);
const sku = skuContainer.attr(`sku`);
numImages = skuContainer.find(`.skuImgContainer`).length;
let i = 0;
skuContainer.find(`.skuImgContainer`).each(function() {
i++;
sic = $(this);
const skuImg = sic.find(`.skuImg`);
const imgContainer = skuImg.find(`.imgContainer`);
const img = imgContainer.find(`img:first`);
cvs = $(`#${img.attr(`forcanvas`)}`);
imgNum = parseInt(skuImg.attr(`imgnum`));
const filename = `${sku}${imgNum > 1 ? `-alt${imgNum}` : ``}.jpg`;
img.attr(`filename`, filename);
if (cvs.length) {
createImages(cvs[0], imgNum, filename,i);
} else { //if an image already exists, we didn't create a canvas for it and we don't need to recreate it.
numImagesProcessed++;
}
if (sic.find(`.useForSeasonal`).is(`:checked`)) {
kpData.append(`parentImage`, filename);
}
});
});
sgiArr = [`L`, `LI`, `I`, `K`, `Y`];
function createImages(loadedData,imgNum,filename,i) {
const mime_type = `image/jpeg`;
var cvs = document.createElement(`canvas`);
//Create the detail version of the image
cvs.width = 800;
cvs.height = 800;
ctx = cvs.getContext(`2d`);
ctx.drawImage(loadedData, 0, 0, 800, 800);
if (imgNum === 1 && sgiArr.indexOf(filename.split(`-`)[2]) >= 0) {
// attach the size watermark to our primary image if it's a kid's product
let watermark = document.getElementById(`sgi${filename.split(`-`)[2]}`);
ctx.drawImage(watermark, 10, 720);
}
const newImageData = cvs.toDataURL(mime_type);
const result_image_obj = new Image();
result_image_obj.src = newImageData;
if (imgNum === 1 && sgiArr.indexOf(filename.split(`-`)[2]) >= 0) {
// display the image if we've attached the size watermark to it
$(`img[filename="${filename}"]`).attr(`src`, result_image_obj.src);
}
cvs.toBlob((blob) => {
let file = new File([blob], filename, { type: `image/jpeg` });
kpData.append(`detail`, file, filename);
}, `image/jpeg`,0.96);
//create the general image
cvs.width = 370;
cvs.height = 370;
cvs.getContext(`2d`).drawImage(loadedData, 0, 0, 370, 370);
cvs.toDataURL(mime_type);
cvs.toBlob((blob) => {
let file = new File([blob], filename, { type: `image/jpeg` });
kpData.append(`general`, file, filename);
}, `image/jpeg`,0.96);
//create the thumbnail
cvs.width = 240;
cvs.height = 240;
cvs.getContext(`2d`).drawImage(loadedData, 0, 0, 240, 240);
cvs.toDataURL(mime_type);
cvs.toBlob((blob) => {
let file = new File([blob], filename, { type: `image/jpeg` });
kpData.append(`thumb`, file, filename);
}, `image/jpeg`,0.96);
//create the repository image for Amazon, Zulilly, Zappos and our wholesale customers. Zullily has the greatest minimum requirements so we'll use those for everyone
loadedData.toBlob((blob) => {
let file = new File([blob], filename, { type: `image/jpeg` });
repositoryData.append(`imgfiles`, file, filename);
numImagesProcessed++;
console.log(`repository data created: `, numImagesProcessed, imgNum);
if (numImagesProcessed === numImages) { // the process can get to here yet not all the previous .toBlob statments from previous images may have completed.
console.log(`finished. Trigger save`);
saveit();
}
}, `image/jpeg`, 0.92);
}
我试过用一系列的承诺:
skuContainer.find(`.skuImgContainer`).each(function() {
promises.push(processSku($(this),sku));
});
$.when.apply($, promises).done(function() {
console.log(`promises are done:`,numFiles, numFilesCreated);
saveit();
});
那就更糟了。done函数甚至在第二次迭代完成之前就启动了。我尝试在每个.toblob函数中递增一个计数器,但计数器没有在“if(counter===NumFileStocreate)saveIt();”的时间内递增
我不知所措。
谢谢
您很可能希望使用promise.all
方法。我知道你在评论中说它不起作用,但我想展示一个起作用的例子。如果这在您的实例中不起作用,那么为了在这个论坛上获得帮助,创建一个演示您的确切问题的MRE可能是最有益的。一些可以运行的东西。
null
var promisesArray = [
new Promise((resolve, reject) => {
setTimeout(() => {
console.log('promise 1 done!');
resolve('');
}, 300);
}),
new Promise((resolve, reject) => {
setTimeout(() => {
console.log('promise 2 done!');
resolve('');
}, 5);
}),
new Promise((resolve, reject) => {
setTimeout(() => {
console.log('promise 3 done!');
resolve('');
}, 50);
}),
new Promise((resolve, reject) => {
setTimeout(() => {
console.log('promise 4 done!');
resolve('');
}, 500);
})
];
async function ResolveAll() {
await Promise.all(promisesArray);
console.log('after all promises');
}
ResolveAll();