Come utilizzare quando quindi inviare il caricamento del file in sequenza in una funzione anche una promessa differita?

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

Domanda

Intendo caricare una serie di file usando jQuery.

Questa intenzione è avvolta in una funzione chiamata uploadFilesUsingAjax();

var uploadFilesPromise = uploadFilesUsingAjax();

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

Devo aspettare che tutti i file vengano caricati correttamente prima di fare qualcos'altro.

all'interno uploadFilesUsingAjax(),

Ho scritto il mio codice in questo modo

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!')});
.

Sfortunatamente, non sono stato in grado di caricare un sacco di file prima di essere reindirizzato alla pagina di successo.

Ho provato varie soluzioni Stackoverflow su come farlo.Finora nulla funziona.Si prega di avvisare.

Alcuni codice sono stati troncati per risparmiare spazio.

È stato utile?

Soluzione

Tutte le tue promesse sono parallele e non sequenziali.

Una promessa rappresenta un'attività già in esecuzione . Promesse in JavaScript, a differenza dei compiti C # o di altre astrazioni sono già iniziate. Il modo per rappresentare un compito che non ha avviato è una funzione che ritorna una promessa.

Poiché promises[i] è già una promessa - quando si esegue promise.then(object) non aggiunge un gestore .then, ma piuttosto restituire immediatamente. .then ignora eventuali argomenti che non sono una funzione.

Questo è il motivo per cui restituisce presto, ritorna non appena la prima promessa soddisfa. Inoltre, non hai bisogno del .when. Creare una funzione che crea un processo di caricamento come tale:

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
   }
}
.

Ora puoi mappare i file alle attività:

 var tasks = files.map(createUploadTask);
.

Nota, che ora le attività sono le funzioni restituiscono una promessa su un caricamento del file. Non sono promesse.

Ora, puoi incatenarli:

 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;
.

Ora ora non è necessario utilizzare quando, dal momento che si restituisce una promessa single . Suppongo che non sia necessario il risultato effettivo qui (ma solo per conoscere il successo / il fallimento).

fai semplicemente:

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top