次に、遅延約束である関数でファイルアップロードを順番に送信するときに使用する方法?

StackOverflow https://stackoverflow.com//questions/23065705

質問

jQueryを使ってファイルの配列をアップロードするつもりです。

この意図は、uploadFilesUsingAjax()と呼ばれる関数で折り返されます。

var uploadFilesPromise = uploadFilesUsingAjax();

$.when(uploadFilesPromise).done(function (uploadFilesAjaxResult) {
        // redirect to success page...
.

何か他のものをする前に、すべてのファイルを正常にアップロードするのを待つ必要があります。

uploadFilesUsingAjax()

私はこのようにして私のコードを書きました

function uploadFilesUsingAjax() {
    var files = pages; // pages is a global variable which is an array of files
    var url = "/users/" + currentUser.id + "/files.json";
    var type = "POST";

    console.info('files length:' + files.length);
    if (files.length > 0) {

        var promises=[];
        for (var i = 0; i < files.length; i++) {
            var data = new FormData();
            var postData = {};
            var file = files.getByIndex(i);
            var key = i + 1;
            if (typeof (file.id) !== "undefined" && file.id > 0) {
                data.append(key, JSON.stringify(file));
            } else {
                data.append(key, file);
            }
            var request = $.ajax({
                //this is the php file that processes the data 
                url: url,

                //POST method is used
                type: type,

                //pass the data
                data: data,

                //Do not cache the page
                cache: false,

                xhr: function() {
                    // custom xhr
                    myXhr = $.ajaxSettings.xhr();
                    if(myXhr.upload) { // check if upload property exists

                            myXhr.upload.addEventListener('progress',updatePagesProgress, false); // for handling the progress of the upload
                    }
                    return myXhr;
                },

                // DO NOT set the contentType and processData
                // see http://stackoverflow.com/a/5976031/80353
                contentType: false,
                processData: false,

                //success
                success: function (json) {
                    // json is already an object thanks to cakephp code to serialize

                    //if POST is a success expect no errors
                    if (json.error == null && json.result != null) {
                        currentUser = json.result.User;
                    // error
                    } else {
                        alert(json.error);
                    }
                }
            });
            promises.push( request);
        }

        var promise = promises[0];
        for (var i = 1; i < promises.length; i++) {
          promise = promise.then(promises[i]);
        }

        return promise.done(function () { console.log('all!')});
.

残念ながら、私は成功ページにリダイレクトされる前にたくさんのファイルをアップロードすることはできませんでした。

これを行う方法については、さまざまなスタックオーバーフローソリューションを試してみました。これまでのところ何も機能しません。アドバイスしてください。

スペースを節約するためにいくつかのコードが切り捨てられました。

役に立ちましたか?

解決

すべての約束は並行してシーケンシャルではありません。

Promiseは、既に既に稼働しているタスクを表します。 C#タスクや他の抽象化とは異なり、JavaScriptでの約束はすでに開始されています。開始されていないタスクを表す方法は、約束を返す機能です。

promises[i]はすでに約束です - promise.then(object)を実行すると、それは。 .then関数ではない引数を無視します。

これが早く戻ってきた理由は、最初の約束が果たすとすぐに返します。 .whenも必要ありません。そのようなアップロードプロセスを作成する関数を作成します。

function createUploadTask(file,i){
    return function(){
         var data = new FormData();
         var postData = {};
         var file = files.getByIndex(i);
         var key = i + 1;
         if (typeof (file.id) !== "undefined" && file.id > 0) {
             data.append(key, JSON.stringify(file));
         } else {
             data.append(key, file);
         }
         return $.ajax({...}); // return the promise
   }
}
.

今、あなたはタスクにファイルをマッピングすることができます:

 var tasks = files.map(createUploadTask);
.

注意事項は、ファイルのアップロードを介した約束を返す各関数です。彼らは約束されていません。

今、あなたはそれらをチェーンすることができます:

 var p = tasks[0](); // start off the chain
 for(var i = 1; i < tasks.length; i++){
      // chain the next task, note, that we're passing a _function_ here
      // when you return a promise from a `.then` it will fulfill when that promise 
      // fulfills, in our case the $.ajax
      p = p.then(tasks[i]); 
 }
 return p;
.

あなたは今 single 約束を返すので、あなたは今使用する必要はありません。私はあなたがここでの実際の結果を必要としないと思います(しかし、成功/失敗を知るためだけに)。

単にする:

 function uploadFilesUsingAjax() {
     // settings
     if(tasks.length === 0){
          // a method MUST always either return either synchronously or asynchronously never
          // both, always return a promise. Otherwise you get API hell.
          var d = $.Deferred();
          d.reject(new Error("Called uploadFiles with no files to upload"));
          return d.promise;
     }
     tasks = pages.map(createUploadTask)
     var p = tasks[0](); // call first one
     for(var i = 1; i < tasks.length; i++) p = p.then(tasks[i]);
     return p; 
 }
.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top