JS等待函数中的几个事件完成

时间:2014-04-29 16:07:26

标签: javascript jquery events

我有一个上传图片并在页面上显示的功能。我该如何等待功能完成?

$("#images").change(function(){
        updateArray(this);
        addImages();
    });

function updateArray(inp)
    {
        for(var i=0,file; file = inp.files[i]; i++)
        {
            var reader = new FileReader();
            reader.onload = function (evt)
            {
                images[images.length] = evt.target.result;
            }
            reader.readAsDataURL(file);
        }
    }

我想在updateArray()中的所有事件完成后调用addImages()

2 个答案:

答案 0 :(得分:4)

我会在这里使用jQuery的deferred/promises。这将允许您等到每个 onload完成,然后触发回调。

以下是一个例子:

function updateArray(inp)
{
    var promises = [];
    for(var i=0,file; file = inp.files[i]; i++)
    {
        var reader = new FileReader(),
            d = new $.Deferred();

        promises.push(d);
        // Make sure we "capture" the correct 'd'
        (function(d){
            reader.onload = function (evt)
            {
                images.push(evt.target.result);
                d.resolve();
            }
        }(d));
        reader.readAsDataURL(file);
    }

    return $.when.apply($, promises);
}

这将为每个FileReader创建一个新的延迟对象。当每一个完成时,其相应的延期将被解决。 $.when用于将所有延迟合并为一个。因此,在您的.change()中,您可以这样做:

$("#images").change(function(){
    updateArray(this).done(function(){
        addImages();
    });
});

P.S。您还可以将参数传递给resolve()以在.done()回调中使用。因此,您可以执行images

,而不是附加到d.resolve(evt.target.result);数组
(function(d){
    reader.onload = function (evt)
    {
        d.resolve(evt.target.result);
    }
}(d));

然后在.done()中,你可以这样做:

$("#images").change(function(){
    updateArray(this).done(function(){
        // Each '.resolve' added a new parameter to here, let's get them all
        images = [].slice.call(arguments, 0);
        addImages();
    });
});

答案 1 :(得分:1)

有几种方法可以解决这个问题,但是如果你使用jQuery(你似乎是这样),我建议你研究一下promises(参见:http://api.jquery.com/promise/)。

对于延迟回调,它们是一种更现代的范例,它具有一些基于成功完成,失败以及将始终处理的函数执行函数的语义处理。