2011-02-08 8 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 "を選択します。 Deferred Objectを何らかの方法で使用して、「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); 
    } 
}, 

だから、繰延オブジェクトを返しません。

this.trigger("UploadComplete", files);

だから我々は単にあなたのアップローダーにバインドする必要があり、

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

私はプラグインすることを使ったことがないが、このshould作品:代わりにuploadNext関数内のコード行があります。がんばろう。

あなたはDeferredの作り方を使用する必要がある場合、あなたは常にこの擬似コードのようなものができます:架空のアップロードセッションのコンテキストで

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

@レイノス...返事をありがとう。これはすばらしく見えますが、ソースコードを変更することは考えていませんでしたが、それは素晴らしいアイデアです!私はオフィスに戻って何が起こったのかを知らせるときにこれを試してみます。 – Hristo

+0

@hristoあなたはソースコードを変更するよう提案していません。私はあなたがイベントを使用することをお勧めします。また、必要な場合は、イベントを遅延オブジェクトと組み合わせることもできます。サードパーティのライブラリを使用していることは、ソースコードを変更していないことです。この方法で、バグを修正して改善をもたらすコードの新しいリリースに頼ることができます – Raynos

+0

@Raynos ...あなたは良い点を作っています。だから私はあなたの例を読んで、それはよさそうだ。私はそれを試してみますが、私は質問があります... Deferredオブジェクトのあなたの例は、 '.click()'イベントハンドラを一時停止し、 'def.done()'の終了後に続行しますか?クリックイベント全体?そうであれば、 'event.preventDefault()'のように呼び出すと、クリックを一時停止し、 'def.done()'の実行後に何らかの方法でそれを続けますか? – Hristo

-1

はい。 jQueryの新しいajax APIの遅延点は、コードが他の非同期コードを待つことができるようにすることです。

お互いに依存する複数の非同期コールがある場合は、すべての完了後に何らかのアクションを実行できるようになります。同じ考え方がここに適用されます。

+2

いくつかのコードを示すマインド? – Hristo

3

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

これらは、我々がアップロードしたいファイルです。ときにすべて

var uploads = files.map(upload_one); 

我々は$ .when(呼び出し)繰延オブジェクトのこの配列を持つと我々はまた、何が失敗したときに、それぞれのアップロード後に何をするかを指定し、:のは、各アップロードの繰延を目的としている別の配列を組み立ててみよう

$.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; 
} 
関連する問題