2016-07-25 9 views
0

In meinem Code lade ich Daten von Json mit d3.json - und um es zum Laufen zu bringen rufe ich eine andere Funktion auf, sobald die Daten geladen sind und den JSON dort zur Verarbeitung übergeben. Dies scheint zu funktionieren, aber weigert sich immer noch, etwas anderes als "undefiniert" zurückzugeben.Warum kann ich console.log (Variable) bekommen, um meinen Wert zu geben, aber keine Variable zurückgeben?

Mein Code:

function GetDataFromJson() { 
     var jsonData; 
    d3.json("http://localhost:8000/pipeline.json", function(dataFromServer){ 
     jsonData = dataFromServer; 
      NewValue(jsonData); 
    }); 
    } 

und

function NewValue(data){ 
    var jsonData = data; 
    headers = ["Won"]; 
    var myTotal = 0; 
     chunks = (headers.map(function(priceRange) { 
      return jsonData.map(function(d) { 
      return {y: +d[priceRange]}; 
      }); 
     })); 
     var myTarget = 10000000; 
     chunks.forEach(function (arrayItem) 
      { 
      var l = 12; 
      for(var i = 0; i < l; i++) { 
       myTotal += arrayItem[i].y; 
      }; 
      }); 
     myTotal = myTotal/myTarget*100; 
     return myTotal; 
} 

Ich laufe dies in Firefox Firebug GetDataFromJson() verwenden und mit dem Code oben als Service-Leistung erhalte ich "undefined" gerade in der Konsole. Wenn ich eine Zeile console.log(myTotal) vor der Return-Anweisung ich bekomme "undefiniert" und "37.5" als 2 separate Zeilen zurückgegeben - 37,5 ist der richtige Wert aus den Daten, die ich analysiert.

Warum gibt nicht zurückgeben myTotal als das Ergebnis der Funktion, während console.log() ist?

Hinzufügen Json Daten

[ 
    { 
    "Month": "Jan", 
    "Prospecting": 0, 
    "Qualifying": 0, 
    "Demonstrating": 0, 
    "Negotiating": 0, 
    "Won": 1000000, 
    "Lost": 350000 
    }, 
    { 
    "Month": "Feb", 
    "Prospecting": 0, 
    "Qualifying": 0, 
    "Demonstrating": 0, 
    "Negotiating": 0, 
    "Won": 750000, 
    "Lost": 2750775 
    }, 
    { 
    "Month": "Mar", 
    "Prospecting": 0, 
    "Qualifying": 0, 
    "Demonstrating": 0, 
    "Negotiating": 250000, 
    "Won": 2000000, 
    "Lost": 750000 
    }, 
    { 
    "Month": "Apr", 
    "Prospecting": 0, 
    "Qualifying": 0, 
    "Demonstrating": 0, 
    "Negotiating": 1375000, 
    "Won": 0, 
    "Lost": 0 
    }, 
    { 
    "Month": "May", 
    "Prospecting": 0, 
    "Qualifying": 0, 
    "Demonstrating": 750000, 
    "Negotiating": 0, 
    "Won": 0, 
    "Lost": 0 
    }, 
    { 
    "Month": "Jun", 
    "Prospecting": 0, 
    "Qualifying": 0, 
    "Demonstrating": 325000, 
    "Negotiating": 0, 
    "Won": 0, 
    "Lost": 0 
    }, 
    { 
    "Month": "Jul", 
    "Prospecting": 0, 
    "Qualifying": 50000, 
    "Demonstrating": 1000000, 
    "Negotiating": 0, 
    "Won": 0, 
    "Lost": 0 
    }, 
    { 
    "Month": "Aug", 
    "Prospecting": 10000, 
    "Qualifying": 35000, 
    "Demonstrating": 0, 
    "Negotiating": 0, 
    "Won": 0, 
    "Lost": 0 
    }, 
    { 
    "Month": "Sep", 
    "Prospecting": 12250, 
    "Qualifying": 22500, 
    "Demonstrating": 0, 
    "Negotiating": 0, 
    "Won": 0, 
    "Lost": 0 
    }, 
    { 
    "Month": "Oct", 
    "Prospecting": 0, 
    "Qualifying": 0, 
    "Demonstrating": 0, 
    "Negotiating": 0, 
    "Won": 0, 
    "Lost": 0 
    }, 
    { 
    "Month": "Nov", 
    "Prospecting": 100000, 
    "Qualifying": 325000, 
    "Demonstrating": 750000, 
    "Negotiating": 0, 
    "Won": 0, 
    "Lost": 0 
    }, 
    { 
    "Month": "Dec", 
    "Prospecting": 120000, 
    "Qualifying": 370500, 
    "Demonstrating": 670000, 
    "Negotiating": 0, 
    "Won": 0, 
    "Lost": 0 
    } 
] 
+1

Sie können das nicht tun. http: //blog.slaks.net/2015-01-04/async-method-patterns/ – SLaks

+0

bitte geben sie einige beispiel json data – Ray

+0

Dank @SLaks - Ich lese den blog, und es scheint, ich brauche versprechen, dies zu erhalten, um das ergebnis myTotal von der NewValue-Funktion zu liefern. Ich kann nicht ganz verstehen, wie ich das anhand deines Artikels machen würde - kannst du mir helfen, zu erläutern, wie ich ein Versprechen in diesem Fall benutzen kann? – Zoinks10

Antwort

0

Ihre Funktion GetDataFromJson()undefined zurückkehrt, weil dies das erwartete Verhalten in JavaScript ist: undefined ist die „default“ zurückgegebene Wert, wenn eine Funktion nicht ein spezifiziert zurückgegebenen Wert, und Ihre Funktion GetDataFromJson() hat keine return.

Vorausgesetzt, dass beide Funktionen arbeiten (dh kein Problem mit asynchronen Codes), in Ihrer GetDataFromJson() Funktion sollten Sie diese ändern: für diese

NewValue(jsonData); 

:

return NewValue(jsonData); 

So könnte die Funktion zurückgeben derselbe Wert, den Sie unter console.log sehen.

+1

Leider wird auch "undefiniert" zurückgegeben - obwohl es immer noch NewValue auslöst. – Zoinks10

+0

Deshalb habe ich gesagt "vorausgesetzt, dass beide Funktionen funktionieren", siehe Quiriacus Antwort oben. Aber selbst ohne das asynchrone Problem würde Ihre Funktion "undefined" zurückgeben, weil sie keine "Rückkehr" hatte. –

1

d3.json ist eine asynchrone (nicht blockierende) Funktion. Das heißt, es wird aufgerufen, aber der Programmablauf läuft weiter. Daher ist Ihre GetDataFromJson zurück, bevor d3.json tatsächlich abgeschlossen ist und d3.json zu einem späteren Zeitpunkt abgeschlossen ist, sobald es die JSON-Daten über die HTTP Anfrage abgerufen hat.

Lösung mit Callback-Funktionen:

// Pass a "callback" function that will get called once 
// the asynchronous task of downloading JSON data is finished. 
function GetDataFromJson(callback) { 
    var jsonData; 
    d3.json("http://localhost:8000/pipeline.json", function(dataFromServer){ 
     jsonData = dataFromServer; 
     callback(NewValue(jsonData)); 
    }); 

    // You don't have this return statement in your code, but it's implied. 
    // This line gets called before d3.json is finished. 
    // It's the line that gives you the undefined when you do 
    // console.log(GetDataFromJson(...)); 
    // To test this, try changing it to return "foo", 
    // you will get "foo" instead of undefined. 
    return; 
} 

Und es so nennen:

// The inline callback function we pass will get called 
// once the async task is finished. Then we can handle the result. 
GetDataFromJson(function(result) { 
    console.log(result); 
}); 

Hinweis: Sie können Wege finden, dass HTTP Anfrage synchron zu machen (zu blockieren) und die Art und Weise funktionieren Sie haben es erwartet, aber es ist keine gute Übung.

Wenn Sie mehr darüber erfahren möchten, wie die Event-Loop funktioniert, empfehle ich diesen Vortrag von Philip Roberts auf der JSConf EU 2014 mit dem Namen "What the heck is the event loop anyway?".

+0

Danke - wenn ich das tue, kann ich das console.log (Ergebnis) zum arbeiten bringen - aber wenn ich das zu "Ergebnis zurückgeben" ändere, Ich bekomme "undefined" wieder - die NewValue-Funktion funktioniert gut, aber aus irgendeinem Grund wird Return nicht Ball spielen. – Zoinks10

+0

Dies ist das gleiche Verhalten, das ich bekomme, wenn ich es genauso wie meinen ursprünglichen Beitrag aufruft - ich dachte, NewValue (jsonData) aufzurufen würde sicherstellen, dass der Code darauf wartet, dass jsonData in diesem Setup geladen wird, bevor er NewValue aufruft - und wenn ich trete. Logge die Elemente in NewValue ein (zB "data", "chunks", myTotal "etc. sie sind alle mit den richtigen Daten gefüllt). – Zoinks10

+0

Ich habe das erste Code-Snippet in meiner Antwort bearbeitet, um dir bessere Einblicke zu geben, warum du das nicht machen kannst Normaler Return-and-Grab-Wert-Fluss, wenn Async-Funktionen beteiligt sind Sie müssen grundsätzlich die Ergebnislogik im Rumpf der Callback-Funktion durchführen Beachten Sie, dass das zweite Argument von d3.json auch eine Callback-Funktion ist , um das Problem anzugehen, das Sie haben. – Kyriakos

Verwandte Themen