2013-07-23 22 views
5

Ho questo sito Web che si collega con un servizio locale che gestisce un CardReader con un Pad PIN. Ci sono molte diverse operazioni che possono essere completate usando questo dispositivo. Ecco un esempio di uno di loro:Come gestire le chiamate AJAX concatenate con jQuery

  1. bloccare il dispositivo
  2. chiedere il numero di PIN
  3. dispositivo di uscita

Prima ho usato per la catena i richiami tra l'altro, ma ora, a causa ci sono nuove operazioni, che usano anche metodi come "lock" e "release", ho bisogno di cambiare il mio codice, in modo che il codice per i passaggi 1 e 3 sia riutilizzabile.

Ho cercato di risolvere questo con promesse di jQuery, ma Im abbastanza nuovo a questo, e ho ancora havent davvero capito come funzionano. Qualcuno può darmi una mano?

Questo è un esempio del codice che sto usando ora. Ho rimosso la logica di business dall'interno delle funzioni, per semplificare l'esempio:

var CardReader = { 

    //////////////////// 
    // Different possible messages to the Card Reader 
    //////////////////// 

    lockDevice: function() { 
     this.makeAjaxCall("GET", "/LockDevice", this.lockDeviceCallback); 
    }, 

    getPin: function() { 
     this.makeAjaxCall("POST", "/getPin", this.getPinCallback); 
    }, 

    releaseDevice: function() { 
     this.makeAjaxCall("POST", "/Release", this.releaseDeviceCallback); 
    }, 

    ////////////////// 
    // Callbacks for each message to the Card Reader 
    ////////////////// 

    lockDeviceCallback: function(jqXHR, textStatus) { 
     if (textStatus !== "success") { return; } 
     this.getCardLogin(); 
    }, 

    getCardLoginCallback: function(jqXHR, textStatus) { 
     if (textStatus !== "success") { return; } 
     this.releaseDevice(); 
    }, 

    releaseDeviceCallback: function(jqXHR, textStatus) { 
     if (textStatus !== "success") { return; } 
     //End 
    }, 

    //////////////// 
    // Other methods 
    //////////////// 

    init: function() { 
     // UI BIndings 
     $(#button).on("click", this.logIn.bind(this)); 
    }, 

    logIn: function() { 
     this.lockDevice(); 
    }, 

    makeAjaxCall: function(callType, resource, callbackMethod) { 

     $.ajax({ 
      type  : callType, 
      url  : "http://localhost:1337" + resource, 
      cache  : false, 
      dataType : "json", 
      contentType: "application/json", 
      context : this, 
      complete : callbackMethod 
     }); 
    } 
}; 

risposta

1

Questo potrebbe soddisfare le vostre esigenze, anche io non sono sicuro di comprendere appieno la vostra problematica qui.

Il punto importante qui sembra mantenere l'ordine sui callback del metodo ajax. Si potrebbe fare qualcosa di simile:

creare questi metodi:

_nextCall: function (deferreds, method) { 
     if (deferreds.length) this._when(deferreds, method); 
     else console.log(method + " SUCCESS"); 
    }, 
    _when: function (calls, method) { 
     var $promise = $.when(this[calls[0]]()) 
     $promise.then(function() { 
      calls.splice(0, 1); 
      this._nextCall(calls, method); 
     }, function() { 
      console.log(method + " FAILED on: " + calls[0]); 
     }); 
    }, 

utilizzarlo come quella per esempio:

logIn: function logIn() { 
     var calls = ["lockDevice", "getCardLogin", "releaseDevice"]; 
     this._when(calls, arguments.callee.name); 
    }, 
    getPinOnly: function getPinOnly() { 
     var calls = ["getPin"]; 
     this._when(calls, arguments.callee.name); 
    }, 

DEMO

codice completo:

var CardReader = { 

    //////////////////// 
    // Different possible messages to the Card Reader 
    //////////////////// 

    lockDevice: function() { 
     return this.makeAjaxCall("GET", "/LockDevice", this.lockDeviceCallback); 
    }, 
    getCardLogin: function() { 
     return this.makeAjaxCall("POST", "/getCardLogin", this.getCardLoginCallback); 
    }, 
    getPin: function() { 
     return this.makeAjaxCall("POST", "/getPin", this.getPinCallback); 
    }, 

    releaseDevice: function() { 
     return this.makeAjaxCall("POST", "/Release", this.releaseDeviceCallback); 
    }, 

    ////////////////// 
    // Callbacks for each message to the Card Reader 
    ////////////////// 

    lockDeviceCallback: function (jqXHR, textStatus) { 
     console.log("lockDeviceCallback"); 
     if (textStatus !== "success") { 
      return; 
     } 
    }, 

    getCardLoginCallback: function (jqXHR, textStatus) { 
     console.log("getCardLoginCallback"); 
     if (textStatus !== "success") { 
      return; 
     } 
    }, 
    getPinCallback: function (jqXHR, textStatus) { 
     console.log("getPinCallback"); 
     if (textStatus !== "success") { 
      return; 
     } 
    }, 

    releaseDeviceCallback: function (jqXHR, textStatus) { 
     console.log("releaseDeviceCallback"); 
     if (textStatus !== "success") { 
      return; 
     } 
     //End 
    }, 

    //////////////// 
    // Other methods 
    //////////////// 

    init: function() { 
     // UI BIndings 
     $('#btn_login').on("click", $.proxy(this.logIn, this)); 
     $('#btn_getPinCallback').on("click", $.proxy(this.getPinOnly, this)); 
    }, 
    _nextCall: function (deferreds, method) { 
     if (deferreds.length) this._when(deferreds, method); 
     else console.log(method + " SUCCESS"); 
    }, 
    _when: function (calls, method) { 
     var $promise = $.when(this[calls[0]]()) 
     $promise.then(function() { 
      calls.splice(0, 1); 
      this._nextCall(calls, method); 
     }, function() { 
      console.log(method + " FAILED on: " + calls[0]); 
     }); 
    }, 
    logIn: function logIn() { 
     var calls = ["lockDevice", "getCardLogin", "releaseDevice"]; 
     this._when(calls, arguments.callee.name); 
    }, 
    getPinOnly: function getPinOnly() { 
     var calls = ["getPin"]; 
     this._when(calls, arguments.callee.name); 
    }, 

    makeAjaxCall: function (callType, resource, callbackMethod) { 

     return $.ajax({ 
      type: callType, 
      url: "/echo/json", // + resource, 
      cache: false, 
      dataType: "json", 
      contentType: "application/json", 
      context: this, 
      success: callbackMethod 
     }); 
    } 
}; 

CardReader.init(); 
1

Utilizzare una libreria promesse più completa. Date un'occhiata a: https://github.com/kriskowal/q Vale la pena dedicare un po 'di tempo a capire perché migliora notevolmente lo stile e la leggibilità del vostro codice. Fondamentalmente si può scrivere ogni funzione aziendale in modo restituisce una promessa, in modo da qualcosa di simile a quanto segue: -

function myBusinessFunction(params) { 
    var deferred = Q.defer(); 
    .... 
    doSomeAsyncFunction(params,function(error,result) { 
     if (error) { 
      deferred.reject(new Error(error)); //pass the error on 
     } else { 
      deferred.resolve(result); 
     } 
    }); 
    return deferred.promise; 
} 

Allora, cosa sta succedendo qui è per ogni operazione asincrona che fate creare una funzione, all'interno che creano un differite e restituirlo. Non appena si ottiene un timeout o un errore o qualsiasi risultato, si chiama deferred.reject o deferred.resolve.

Con questa aggiunta al codice si può quindi evitare l'inferno richiamata in cui hai un sacco di funzioni nidificate e creare il tuo qualcosa di complesso codice di algoritmo come il seguente: -

Q.fcall(promisedStep1) 
.then(promisedStep2) 
.then(promisedStep3) 
.then(promisedStep4) 
.then(function (value4) { 
    // Do something with value4 
}) 
.catch(function (error) { 
    // Handle any error from all above steps 
}) 
.done(); 

Questo ricorda da vicino la prova ... cattura la programmazione in stile procedurale che è così familiare ma in realtà stai gestendo i processi asincroni. Quando si chiama lo scarto sulla promessa, il flusso di controllo passerà alla funzione di cattura semplificando notevolmente la programmazione.

Ci sono molte funzioni e funzioni aggiuntive nella libreria in modo da essere in grado di gestire i passaggi in esecuzione in parallelo e così via.Guarda i documenti ne vale la pena.

1

Prova async: false con la vostra chiamata Ajax. Questa prima operazione completa la chiamata Ajax e quindi esegue altre istruzioni.

makeAjaxCall: function (CALLTYPE, risorsa, callbackMethod) {

$.ajax({ 
     type  : callType, 
     url  : "http://localhost:1337" + resource, 
     cache  : false, 
     dataType : "json", 
     contentType: "application/json", 
     context : this, 
     async :false, 
     complete : callbackMethod 
    }); 
} 
-1
 jQuery.support.cors = true; 

     $.ajax({ 
      type: "POST", 
      contentType: "application/json; charset=utf-8", 
      datatype: "json",    
      async :false, 
      url: "http://yourHost:portnumeber/ServiceName/LockDevice", 
      success: 
     lockDeviceCallback, 
      error: 
     function (XmlHttpRequest, textStatus, errorThrown) { 
      errorHandler(XMLHttpRequest); 
     } 
     });    
Problemi correlati