2016-04-23 4 views
0

Ich versuche das einfachste Diagramm (beliebigen Typs) mit Daten aus einer externen JSON-Datei. Ich benutze plotly.js, die eine Erweiterung von d3js ist. Kein Plotten durch d3js, wenn Daten mit einer Variablen verknüpft sind

Dies ist der Teil von Interesse:

var dates = [], scores = []; 
var user_json = 'https://hacker-news.firebaseio.com/v0/user/anton_tarasenko.json'; 
var item_json = 'https://hacker-news.firebaseio.com/v0/item/'; 

$.getJSON(user_json, function (user) { 
    $.each(user.submitted, function(i, item_id) { 
     $.getJSON(item_json + item_id + '.json', function(item) { 
      if (item.type == 'story') { 
       scores.push(Number(item.score)); 
       dates.push(Number(item.time)); 
      } 
     }); 
    }); 
}); 

var data = [{ 
    x: dates, 
    y: scores, 
    mode: 'lines+markers', 
    type: 'scatter' 
}]; 
Plotly.newPlot('myDiv', data); 

Dies gibt ein leeres Grundstück. Aber wenn ich ersetzen x: dates mit x: [1461189218, 1460844086, ... , 1427738937] und y: scores mit y: [1, 154, ..., 1] (Ausgabe von console.log(dates) und log(scores)), es funktioniert gut.

Warum ignoriert die Bibliothek Verweise auf Arrays? Ich denke, ich missbrauche Variablen, aber nicht sicher, wie.

Irgendwelche Ideen?

Antwort

1

Ihr Problem liegt in der Art der asynchronen Programmierung. Da $.getJSON() asynchron ist, wird der gesamte nachfolgende Code tatsächlich ausgeführt, bevor das Partitur- oder Datumsfeld gefüllt wurde.

Damit Ihr Code wie vorgesehen funktioniert, können Sie den gesamten verbleibenden Code in den Callback verschieben (und jedes Element plotten) oder Versprechungen verwenden (und einmal mit allen Daten plotten). Mit jQuery können Sie relativ einfach mit Versprechen arbeiten.

var user_json = 'https://hacker-news.firebaseio.com/v0/user/anton_tarasenko.json'; 
var item_json = 'https://hacker-news.firebaseio.com/v0/item/'; 

// Main 

getUser() 
    .then(getScoresAndDates) 
    .then(plot); 

// Declarations 
function all(arrayOfPromises) { 
    return jQuery.when.apply(jQuery, arrayOfPromises).then(function() { 
    return Array.prototype.slice.call(arguments, 0); 
    }); 
} 

function getUser() { 
    return $.getJSON(user_json); 
}; 

function getScoresAndDates(user) { 

    var scoresAndDates = []; 

    $.each(user.submitted, function(i, item_id) { 
    scoresAndDates.push($.getJSON(item_json + item_id + '.json')); 
    }); 

    return all(scoresAndDates); 
} 

function plot(result) { 
    scoresAndDates = result 
    .map(function(v){ 
    return v[0]; 
    }) 
    .filter(function(v) { 
    return v.type == 'story'; 
    }) 

    var scores = scoresAndDates.map(function(v) { 
    return v.score 
    }); 
    var dates = scoresAndDates.map(function(v) { 
    return v.time 
    }); 

    var data = [{ 
    x: dates, 
    y: scores, 
    mode: 'lines+markers', 
    type: 'scatter' 
    }]; 

    Plotly.newPlot('myDiv', data); 
} 
1

Ich denke, das ist ein asynch Problem. Versuchen Sie, Ihren Code in den Rückruf zu setzen:

Dies ist keine sehr elegante Lösung, aber es sollte funktionieren.

+0

Vielen Dank: es war async. Ich habe "newPlot" nach "push" verschoben, so dass es jetzt jedes Mal neu gezeichnet wird, wenn es eine neue Nummer bekommt. –