2011-02-08 35 views
4

我在表单中使用了Plupload file uploader。我想定制它,以便当表单被提交时,即点击“提交”按钮时,发生的第一件事是文件上传,然后提交表单。如何使用jQuery.Deferred对象来等待异步函数调用完成?

从我所知道的情况来看,我可能对此有错,但看起来uploader.start()是一个异步函数调用。所以目前,上传将开始,表单将在文件上传之前提交。问题是我无法控制这个函数调用。

我最近阅读了关于new release of jQuery 1.5和新的Deferred Object,它似乎有可能帮助我解决这个问题。是否有办法等待异步函数调用完成其工作,然后在调用后继续执行代码。所以我在寻找类似下面的伪代码...

var uploader = $('#plupload_container').pluploadQueue(); 

$('#submitButton').click(function() { 

    // if there are files to be uploaded, do it 
    if (uploader.files.length > 0) { 

     // make the call and wait for the uploader to finish 
     uploader.start(); 
     while (the uploading is not done) { 
     wait for the uploader to finish 
     } 

     // continue with submission 
    } 
}); 

有没有办法为“等待” uploader.start()完成,基本上是把一个暂停的单击事件处理程序,使所有的文件可以先上传,然后点击事件处理程序的其余部分可以完成执行?我试过以下,但完成文件上传前“完成”印...

$.when(uploader.start()).then(function() { 
    console.log("done") 
}); 

另一个有价值的信息片......我的某些事件绑定到这个uploader对象实例,如“ UploadProgress“或”UploadComplete“。例如,我可以在发生“UploadComplete”事件时以某种方式使用延迟对象来捕获事件吗?有没有AJAX-y的方式来做到这一点?

谢谢。

回答

5

你的问题是,虽然uploader.start做代码异步的工作,uploader.start必须返回一个jquery $.deferred对象。

从您上传插件的最新源:

/** 
* Starts uploading the queued files. 
* 
* @method start 
*/ 
start : function() { 
    if (this.state != plupload.STARTED) { 
     this.state = plupload.STARTED; 
     this.trigger("StateChanged"); 
     uploadNext.call(this); 
    } 
}, 

所以它不返回延期对象。相反,在uploadNext功能有这行代码:

this.trigger("UploadComplete", files);

所以我们只需绑定到你的上传,

uploader.bind("UploadComplete", function(files) { 
    // your code 
}); 

我从来没有使用的插件,但这个should工作。祝你好运。

如果你必须使用deferreds那么你可以随时像这样的伪代码:

var uploader = $('#plupload_container').pluploadQueue(); 
var def = $.Deferred(); 
uploader.bind("UploadComplete", function(files) { 
    def.resolve(files); 
}); 
$('#submitButton').click(function() { 
    if (uploader.files.length > 0) { 
     uploader.start(); 

     def.done(function(files) { 
      def = $.Deferred(); // reset the deferred object. 
      // rest of your click handler. 
     }); 

    } 
}); 
+0

@Raynos ...谢谢你的回复。这一切看起来不错,我甚至没有想过改变源代码,但这是一个好主意!当我回到办公室时,我会试试这个,让你知道会发生什么。 – Hristo 2011-02-09 23:53:21

-1

是的。在ajax api中,jquery新推迟的一点是允许您的代码等待其他异步代码。

如果您有多个互相依赖的异步调用,则延迟将允许您在完成所有操作后执行一些操作。同样的想法适用于此。

+2

心灵呈现出一些代码? – Hristo 2011-02-08 16:00:10

3

在一个假想的上传会话的上下文:

var files = ["file1.txt", "file2.txt", "file3.txt"]; 

这些都是我们想上传的文件。让我们来装配具有每次上传延期对象的另一个数组:)与这一类递延对象

var uploads = files.map(upload_one); 

我们调用$。当(我们还规定每次上传后做什么,什么时候出现任何故障,而当一切完全完成:

$.when(uploads) 
    .progress(function() { 
    // report to user, step progress bar, etc 
    }) 
    .fail(function() { 
    // display error 
    }) 
    .done(function() { 
    // all uploads finished, do stuff 
    }); 

这是每个单独上传的工作函数。它返回推迟对象,并根据各自的上传也称成功或错误的功能:

function upload_one(file) { 
    var deferred = new $.Deferred(); 
    // start upload 

    // if finished: 
    deferred.notify(); 
    deferred.resolve(); 

    // if failed: 
    deferred.reject(); 

    return deferred; 
}