我有一个图像处理javascript。通过带有id' image_input'的文件输入用户可以选择上传无限数量的图像。当用户上传图像时,我的jQuery代码会捕获它们并为每个图像调用我的图像处理代码。
$('#image_input').change(function() {
var input = $(this);
image_count = input[0].files.length;
for (var i = 0; i < image_count; i++) {
Uploader.processImage(input[0].files[i]);
}
});
过程映像功能会创建一个新的HTML img元素,并将用户上传的图像加载到其中。脚本等待,直到加载图像,然后将其转换为合适的格式和大小。最后,图像被保存到一个数组中:Uploader.images。
Uploader.processImage = function(image) {
var image_element = document.createElement('img');
var image_url = window.URL.createObjectURL(image);
image_element.onload = function() {
image_data = convert(this);
Uploader.images.push(dataUriToBlob(image_data));
}
image_element.src = image_url;
}
我希望图像按照上传的顺序存储在数组中。问题是onload函数是异步的,这意味着我无法控制图像保存的顺序。例如,我选择上传3张图片。图像1和图像2均为10MB大小,但图像3仅为300KB。因此,首先完成图像3的转换,并且阵列中图像的最终顺序为3,1,2(或3,2,1)。
如何同步processImage的执行,以便仅在前一个图像的转换完成后处理下一个图像?
答案 0 :(得分:2)
我认为你应该看看javascript中的锁:
答案 1 :(得分:1)
Locks are great,@ Esse回答。我还建议您查看Fibers(这是我通常使用的)和Promises.js。
This is a great article关于Meteor框架中的Async。它很好地概述了光纤的工作原理。
答案 2 :(得分:1)
我会使用Promises来解决这样的问题。我喜欢实现Q标准的Promises/A+库。
More on Promises on HTML5 Rocks
使用Q和Qimage库制作了一个小图片加载脚本,在与问题类似的情况下显示了Promise的原则:
var arrOfImgUrls = [url1, url2, url3];
//Loads images from an array of URLs
function loadImages(urls) {
var promises = [];
for (var i = 0; i < urls.length; i++) {
//Qimage loads and image from an URL and returns a Promise.
//If the Promise is fullfilled we get an <img> node
//as the resolve value.
//
//We push the Promises on to an array
promises.push(Qimage(urls[i]))
}
//Return the array of Promises
return promises;
}
//Q.all() returns a promise that is fulfilled with an array
//containing the fulfillment value of each promise, or is rejected
//with the same rejection reason as the first promise to be rejected.
Q.all(loadImages(arrOfImgUrls))
//If all Promises are fullfilled the the resolve callback is called
.then(function (imgs) {
//We get an array of <img> nodes in the same order as the
//'arrOfImgUrls'-array
console.log(imgs);
},
//Else the reject callback is called with the same rejection
//reason as the first promise to be rejected.
function (error) {
console.log(error);
});