2017-04-06 1 views
0

Ich habe die folgenden JSON von einem API-Anruf zurückgegeben. Ich möchte überprüfen, ob ein bestimmter Ereignistyp für bestimmte Produkte protokolliert wird, und wenn der richtige Ereignistyp eine entsprechende Nachricht zurückgibt und den Klick-Handler beenden, andernfalls fortfahren. Ich habe eine Funktion namens hasEvent, um diese Prüfung durchzuführen. Aber wenn ich diese Funktion von aufrufen, wird keine Nachricht zurückgegeben, auch wenn die Prüfung wahr ist?jQuery - Rückruf funktioniert nicht

{ 
    "item": { 
    "Event": [ 
     { 
     "EventType": { 
      "Description": "New order" 
      }, 
     "EventSubType": { 
      "Description": "Awaiting payment" 
      } 
     }, 
     { 
     "EventType": { 
      "Description": "New order" 
      }, 
      "EventSubType": { 
      "Description": "Dispatched" 
      } 
     } 
    ], 
    "Errors": { 
     "Result": 0, 
     "Message": "" 
    }, 
    "RecordCount": 2 
    } 
} 


var getEvents = function (callback) { 

    var orderId = $("#Id").val(); 

    $.getJSON('api/events?id=' + orderId) 
     .done(function (data) { 
       callback(data); 
     }).fail(function (jqXHR, textStatus, err) { 
      return; 
     }); 

} 


var hasEvent = function (productType, callback) { 

    var msg; 

    getEvents(function (data) { 

     _.find(data.item.Event, function (event) { 

      if (event.EventType.Description == 'New order' && 
       event.EventSubType.Description == 'Dispatched' && 
       productType = 'xyz') { 

       msg = 'Some message'; 
       return true; 
      } 

      if (event.EventType.Description == 'New order' && 
       event.EventSubType.Description == 'Awaiting payment' && 
       productType = 'xyz') { 

       msg = 'A different message'; 
       return true; 
      } 

      // Check for Some more conditions and return appropriate message 

      return false; 
     }); 

     if (msg) 
     callback(msg); 

    }); 


} 


var someOtherFunction = function() { 

    $('.myselector').click(function (e) { 

     var productType = $(this).attr("data-product-type"); 

     hasEvent(productType, function(msg) { 
      alert(msg); 
      // exit click event handler 
      return; 
     }); 

     // otherwise do some other stuff 

     return false; 
    } 
} 

Was ist falsch mit dem obigen Code?

* UPDATE *

ich den Code aktualisiert habe nach Griffins Lösung durch einen Rückruf an die hasEvent Funktion hinzugefügt, aber jetzt, wie ich den folgenden Click-Handler beende, wenn eine Warnung angezeigt bekommen. Die folgende einfach weiter auszuführen, bis alle Aktionen innerhalb der Click-Handler abgeschlossen sind, das ist nicht das, was ich will - ich will den Handler verlassen, wenn es Ereignisse und Alarm angezeigt:

$('.myselector').click(function (e) { 

    var productType = $(this).attr("data-product-type"); 

    hasEvent(productType, function(eventMsg) { 
     alert(msg); 
     // exit click event handler 
     return; 
    }); 

    // Do some other stuff only if no events 

    return false; 
} 
+0

'// Exit Click Event Handler 'ist was falsch ist. auch '// tu etwas anderes nur, wenn auch keine Ereignisse im Callback sein sollten. gogoasynchronouslogic –

Antwort

0

das Problem in Ihrem Code ist, dass $.getJSON ist asynchron, dh wenn Sie es ausführen, wird eine Operation gestartet, die nicht abgeschlossen wird, bevor die nächste Codezeile ausgeführt wird. Wenn der Vorgang abgeschlossen ist, wird der Rückruf, den Sie an .done übergeben haben, ausgeführt, aber in dieser Zeit wird der Großteil Ihres anderen Codes bereits ausgeführt. Das heißt, wenn Sie hasEvents aufrufen, initialisieren Sie msg zu undefined, dann getEvents einen Rückruf übergeben, der aufgerufen wird, wenn Ihr Ajax-Aufruf zurückkommt. Da dieser Rückruf jedoch nicht sofort ausgeführt wird, wird hasEvents weiter ausgeführt und gibt msg zurück, was immer noch gleich undefined ist, was ein falscher Wert in Javascript ist. Dies bedeutet, dass selbst dann, wenn Ihr Ajax-Anruf zurückkehrt und der Rückruf ausgeführt wird, hasEvent(productType) bereits als falsch ausgewertet wurde.

Eine mögliche Lösung wäre, hasEvent einen zweiten Parameter zu geben, der ein Rückruf ist. Dann in Ihrem _.find, könnten Sie diese Rückruf mit der Meldung ausführen, anstatt es zurückzugeben, wie folgt aus:

var getEvents = function (callback) { 

    var orderId = $("#Id").val(); 

    $.getJSON('api/events?id=' + orderId) 
    .done(function (data) { 
     callback(data); 
    }).fail(function (jqXHR, textStatus, err) { 
     return; 
    }); 

} 


var hasEvent = function (productType, callback) { 

    var msg = null; 

    getEvents(function (data) { 

    _.find(data.item.Event, function (event) { 

     if (event.EventType.Description == 'New order' && 
     event.EventSubType.Description == 'Dispatched' && 
     productType = 'xyz') { 

     msg = 'Some message'; 
     return true; 
     } 

     if (event.EventType.Description == 'New order' && 
     event.EventSubType.Description == 'Awaiting payment' && 
     productType = 'xyz') { 

     msg = 'A different message'; 
     return true; 
     } 

     // Check for Some more conditions and return appropriate message 

     return false; 
    }); 

    callback(msg); 


    }); 


} 

var someOtherFunction = function() { 

    $('.myselector').click(function (e) { 

    var productType = $(this).attr("data-product-type"); 
    hasEvent(productType, function(eventMsg) { 
     if (eventMsg) { 
     console.log(eventMsg); 
     alert(eventMsg); 
     } else { 
     console.log('there was no event!') 
     } 
    }) 
    } 
} 

Alternativ asynchrone jquery Funktionen verspricht zurückkehren, so dass man, anstatt es wie dies tun könnte:

var getEvents = function (callback) { 
    var orderId = $("#Id").val(); 
    return $.getJSON('api/events?id=' + orderId); 
} 


var hasEvent = function (productType) { 
    return getEvents() 
    .then(function (data) { 

     var foundEvent = _.find(data.item.Event, function (event) { 

     if (event.EventType.Description == 'New order' && 
      event.EventSubType.Description == 'Dispatched' && 
      productType = 'xyz') { 
     } 

     // Check for Some more conditions and return appropriate message 

     return false; // if you don't return, it's undefined, which is a falsy value and has the same effect as returning false in _.find 
     }); 

     return 'some message'; 

    }); 

} 


var someOtherFunction = function() { 

    $('.myselector').click(function (e) { 

    var productType = $(this).attr("data-product-type"); 
    hasEvent(productType) 
     .then(function(eventMsg) { 
     console.log(eventMsg); 
     alert(eventMsg); 
     }); 
    } 
} 
+0

Ich bin nicht sicher, wie ich die hasEvent-Funktion ändern, um einen Rückruf mit der Nachricht zurückzugeben und den Event-Handler zu beenden? Können Sie bitte etwas Code hinzufügen, um dies zu erklären? Ich habe Folgendes versucht - Aktualisierter Beitrag, aber es funktioniert nicht? – adam78

+0

So nichts wird protokolliert oder alarmiert? – Griffin

+0

Ich bekomme Alarm, aber der Wert ist nicht definiert. Auch in der Konsole bekomme ich Fehler '\t Rückruf ist keine Funktion: Rückruf (msg);' für die Zeile innerhalb meiner hasEvent-Funktion. – adam78