如何在 javascript 中同步异步方法

How to synchronize asynchronous methods in javascript?

本文关键字:同步 异步方法 javascript      更新时间:2023-09-26

我有一个图像处理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 的大小仅为 300 KB。因此,首先完成图像 3 的转换,数组中图像的最终顺序为 3, 1, 2(或 3, 2, 1)。

如何同步 processImage 的执行,以便仅在前一个图像的转换完成后处理下一个图像?

我认为

你应该看看javascript中的锁:

https://github.com/Wizcorp/locks

正如@Esse回答的那样,锁很棒。 我还建议查看Fibers(这是我通常使用的)和Promises.js。

这是一篇关于 Meteor 框架中异步的好文章。 不过,它很好地概述了纤维的工作原理。

我会使用承诺来解决这样的问题。我喜欢实现 Promises/A+ 标准的 Q 库。

更多关于 HTML5 摇滚的承诺

使用 Q 和 Qimage 库制作了一个小的图像加载脚本,在类似于问题中的情况中显示了承诺的原则:

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