1

Ich vermute, es ist ein Problem mit der Asynchronität, Ich kann einfach nicht verstehen, was das Problem ist. Also mache ich mehrere API Anfragen und fülle eine Liste mit den Antworten. Dann habe ich ein D3.js-Skript, das die Daten, , die undefined, obwohl, ich ersetzte es mit einem einfachen Protokoll hier. (natürlich die Konsole "wertet" die Werte später in Echtzeit aus, aber die Protokollierung eines Knotens [0] ist in der Tat undefiniert.) Ich habe das Setzen eines Timeouts auf die nachfolgenden Skripte getestet, aber kein Erfolg, und ich konnte nicht kommt mit einer Callback-Lösung daher, da die Anfrage selbst schon ein Callback ist. (ich weiß forEach die richtige Methode ist hier zu verwenden, aber ich versuche auch die Zuordnung funktional mit einer sofortigen Rückkehr zu bekommen, die ich noch nicht geschieht auch etwas könnte)Saved Javascript Facebook API-Antwort bleibt undefined?

variables=["pageid1","pageid2","pageid3"]; 
nodes=[]; 
variables.map(function(variable){ 
    FB.api("/"+variable,"GET",{fields:'name,picture.type(large),engagement'},function(response){ 
     if(!response.error){ 
      nodes.push(response); 
     } 
    }); 
}); 
console.log(nodes); 

Antwort

2

Sie können die Anforderungen in einem Versprechen wickeln. Warten Sie dann, bis alle Versprechen gelöst sind. In diesem Fall haben Sie Ihre Knotenvariable mit Antworten gefüllt. Sie können es wie so tun:

nodes=[]; 
function sendRequest(variable) { 
    return new Promise ((resolve, reject) => { 
     FB.api("/"+variable,"GET",{fields:'name,picture.type(large),engagement'},function(response){ 
      if(!response.error) 
       resolve(response); 
     }); 
    }); 
} 

Promise.all(variables.map(function(variable) { 
    return sendRequest(variable); 
})).then(values => { 
    /* All the responses are solved here */ 
    nodes = values.splice(0); 
    console.log( nodes); 
}); 
1

Ich vermute, dass es ein Problem mit der Asynchronität

Ja ist, natürlich kann Ihre console.log und wird vor dem .api endet. Versuchen, es mit einem setTimeout zu verzögern, ist nur schlechte Programmierung (es ist ein Ratespiel).

Jede Verarbeitung auf nodes muss innerhalb der .api Callback sein. Wenn Sie mehrere asynchrone Anrufe auslösen und sie alle vor dem Verarbeiten nodes beenden müssen, sollten Sie etwas wie d3.queue verwenden. Aus der Dokumentation (fette Mine):

Eine Warteschlange wertet null oder mehr verzögerte asynchrone Tasks mit konfigurierbarem Nebenläufigkeit aus: Sie steuern, wie viele Tasks gleichzeitig ausgeführt werden. Wenn alle Aufgaben abgeschlossen sind oder ein Fehler auftritt, übergibt die Warteschlange die Ergebnisse an Ihren wartenden Rückruf. Diese Bibliothek ähnelt Async.js parallel (wenn Nebenläufigkeit ist unendlich), Serie (wenn Gleichzeitigkeit ist 1) und Warteschlange, aber bietet eine viel kleinere Stellfläche: ab Release 2, d3-Warteschlange ist etwa 700 Bytes gezippt, im Vergleich zu 4.300 für Async.

In Ihrem Fall der Code könnte so (ungetestet) aussehen:

var q = d3.queue(); 

variables.forEach(function(d) { 
    q.defer(FB.api, "/" + variable, , "GET", {fields: 'name,picture.type(large),engagement' }); 
}); 

q.await(function(error, response1, response2, response3) { 
    if (error) throw error; 
    // build out nodes from responses... 
}); 
+0

Hallo, danke für die Cue, ich entfernt 'setTimeout' aus dem Beispiel-Code für es tat mir auch weh. D3 ist einfach genial, eine solche Funktion zu haben. Ich denke, ich werde herausfinden, wie es funktioniert, um die Lösung zu verstehen und vielleicht eine native Lösung zu finden. – bpstrngr

+0

@bpstrngr, hinzugefügt ein bisschen Beispielcode, um loszulegen (leider ist es nicht getestet) – Mark

1

Verschiedene Ansatz mit Asynchron/erwarten und einige Fehlerbehebungen (lassen, Pfeil Funktionen, ...):

let variables = ['pageid1', 'pageid2', 'pageid3']; 
cosnt sendRequest = (variable) => { 
    return new Promise ((resolve, reject) => { 
     FB.api('/' + variable, {fields:'name,picture.type(large),engagement'}, (response) => { 
      if(!response.error) { 
       resolve(response); 
      } else { 
       reject(response.error); 
      } 
     }); 
    }); 
}; 

const getData = async() => { 
    let nodes = []; 
    for (let i = 0; i < variables.length; i++) { 
     let response = await sendRequest(variables[i]); 
     nodes.push(response); 
    } 
    console.log(nodes); 
}; 

getData();