2016-05-12 15 views
0

Hier ist ein Code.Weird Javascript Schließung Bug

function callServiceSync(url, obj) { 
    var result = true; 
    callServiceOptions(url, obj, function(res){ 
     result = res; 
     alert("RESULT CB: "+JSON.stringify(result)); 
    }, {async: false}); 
    alert("RESULT POST-CB: "+JSON.stringify(result)); 
    return result; 
} 

Wenn es läuft, das Warnfeld sagt:

RESULT CB: { "Erfolg": true, "Daten": "dtrombley"}

(das ist, was die Webservice zurückkehrt, in der Realität), und dann:

RESULT POST-CB: true

Warum funktioniert diese Zuweisung an die Schließvariable nicht? Missverstehe ich, wie JS-Schließungen funktionieren?

callServiceOptions() ist ziemlich longwinded - aber die wichtigste davon ist, dass jQuery's $ .ajax-Methode mit seinen letzten Argumenten Optionen in einigen Standard erweitert (in diesem Fall ist async für Sync-Abfrage deaktiviert), und dann ausgeführt wird der bereitgestellte Rückruf.

Ist $ Schnipsel() vielleicht die Ausführung etwas in irgendeiner Art und Weise, die/vermasselt Schließungen deaktiviert (aber ich die cb nennen, nicht .ajax $()!)? Wenn ja, wie repariere ich das?

Der Vollständigkeit (obwohl wirklich diese Funktion nicht in der Lage sein sollte, die Dinge zu meinem Denken vermasseln):

function callServiceOptions(url, obj, cb, options) { 
    optSuccess = options.success; 
    optError = options.error; 
    opts = {} 
    $.extend({},options) 
    if (!opts.contentType) { 
     opts.contentType = "application/json"; 
    } 
    if (!opts.dataType) { 
     opts.dataType = "json"; 
    } 
    if (!opts.data && obj) { 
     opts.data = JSON.stringify(obj); 
    } 
    if (!opts.processData) { 
     opts.processData = false; 
    } 
    if (!opts.method) { 
     opts.method = "POST"; 
    } 
    opts.error = function(jqXHR, textStatus, errorThrown) { 
     if (optError) { 
      optError(jqXHR, textStatus, errorThrown); 
     } 
     if (jqXHR.responseText) { 
      responseObj = JSON.parse(jqXHR.responseText) 
      if (responseObj && responseObj.message) 
      cb({ 
       success: false, 
       message: responseObj.message 
      }) 
      return 
     } 
     cb({ 
      success: false, 
      message: errorThrown 
     }); 
    }; 
    opts.success = function(data, textStatus, jqXHR) { 
     if (optSuccess) { 
      optSuccess(data,textStatus,jqXHR); 
     } 
     cb(data); 
    }; 
    if (url.charAt(0) == '/') { 
     url = url.substr(1); 
    } 
    opts.url = WEBCTX.getBaseURL() + url; 

    $.ajax(opts); 
} 

Dies ist kein Duplikat einer Frage zu stellen, wie ein Wert von einer Asynchron zurückzukehren Veranstaltung. Ich habe eine funktionierende CallServiceAsync(), die das wunderbar macht. Ich benutze synchronen Modus, wenn Sie nicht damit vertraut sind, bitte machen Sie diese Frage ...

+0

Quentin - Bitte lesen Sie die Frage genauer. Ich führe keinen asynchronen Aufruf aus, führe einen synchronen Aufruf aus und der Wert wird korrekt von jQuery ajax() zurückgegeben. – BadZen

+1

Nein, es gibt einen synchronen Abfragemodus, und das verwende ich. Bitte lese die Dokumentation unter http://api.jquery.com/jquery.ajax/ und speziell das Bit über die "async" -Option, die ich benutze. – BadZen

+0

Wenn es asynchron wäre, würden die Warnungen nicht in dieser Reihenfolge zurückgegeben, sondern das Gegenteil. – BadZen

Antwort

6

Ihre Funktion ist asynchron.

Während Sie ein Objekt erstellt haben, das wie {async: false} aussieht, übergeben Sie es als 4. Argument an callServiceOptions, so dass es in die Variable options platziert wird.

Sie nur diese Variable zweimal zugreifen (options.success und options.error), so dass die async Eigenschaft wird nie für etwas (so $.ajax verwendet den Standardwert von true) verwendet.

Hinzufügen console.log(opts) kurz vor dem Anruf $.ajax(opts); wird dies zeigen.

+0

Ah mein Fehler. Ich sah die "Extend" -Logik, ich dachte, dass die Optionen in Optionen erweitert wurden. – Quantastical

+2

@Quantastical, ändert '$ .extend' das erste Argument und gibt es zurück, aber Sie erfassen den Rückgabewert nicht. – trincot

+0

Ook. So war ich. '$ .extend (opts, options)' ist das, was ich natürlich meinte. Schade =) Funktioniert jetzt. – BadZen