2016-07-28 5 views
0

Ich habe die folgende Funktion, die eine API mehrmals aufruft:Javascript Wie abzuspeichern und Antworten von mehreren Asynchron-API-Aufrufe

function define(arr, callback) { 
    var client = []; 
    var definitions = {}; 
    for (var i = 0, len = arr.length; i < len; i++) { 
     (function (i) { 
      client[i] = new XMLHttpRequest(); 
      client[i].onreadystatechange = function() { 
       if (client[i].readyState == 4 && client[i].status == 200) { 
        definitions[arr[i]] = client[i].responseText; 
       } 
      }; 
      client[i].open('GET', 'http://api.wordnik.com:80/v4/word.json/' + arr[i] + 
       '/definitions?limit=200&includeRelated=false&sourceDictionaries=webster&useCanonical=false&includeTags=false&api_key=...', 
       true); 
      client[i].send(); 
     })(i); 
    } 
    return definitions; 
} 

Wie in How do I return the response from an asynchronous call? die return auftritt, bevor die Asynchron-Anrufe die Funktion beenden verursacht zu ein leeres Objekt zurückgeben.

Da ich eine Schleife habe, die viele Anrufe ausführt, kann ich die Lösung von status == 200 mit einem Rückruf nicht verwenden, der zurückgibt, was ich will.

Ich habe versucht, ein globales Variablenobjekt und einen Rückruf, der jedes Mal, wenn es aufgerufen wird, ein neues Schlüsselwertpaar anfügt. Dies funktioniert nicht aus dem gleichen Grund, den der ursprüngliche Code nicht hat.

Ich habe auch versucht, einen Rückruf zu machen, der das Objekt zurückgibt und es an eine andere Funktion weitergibt, die den Aufruf nicht durchführt, bis eine Bedingung erfüllt ist. Dies scheint der vielversprechendste Pfad zu sein, aber ich bin nicht sicher, welche Bedingung ich verwenden könnte, die nur dann wahr wäre, wenn alle asynchronen Aufrufe beendet sind, da der Callback nur Zugriff auf Variablen hätte, die als Argumente übergeben werden.

+0

Werfen Sie einen Blick auf Versprechungen und 'Promise.all', gespeichert wurden http://stackoverflow.com/documentation/javascript/231/Versprechen/925/Warten-für-mehrere-gleichzeitige-Versprechen # t = 201607281713298352612 – Andreas

Antwort

0

Sie könnten Fetch und Versprechungen dafür verwenden. Ofc für ältere Browser müssten Sie some polyfill verwenden.

const urls = [ 
 
    'https://raw.githubusercontent.com/fizyk20/generic-array/master/README.md', 
 
    'https://raw.githubusercontent.com/fizyk20/generic-array/master/src/iter.rs' 
 
]; 
 

 
function getAll(urls) { 
 
    const promises = urls.map(url => { 
 
    return fetch(url) 
 
     .then(response => response.text()); //or response.json() for json data and 
 
     //you can check response.ok property to see if response was successful 
 
    }); 
 
    
 
    return Promise.all(promises); 
 
} 
 

 
getAll(urls) 
 
    .then(txts => console.log(txts.slice(0, 400)));

0

Sie sind fast da.
Sie müssen nur überprüfen, jedes Mal, wenn eine Anfrage beendet/eine zurückgegebene Definition in definitions gespeichert wird, wenn die Anzahl der Ergebnisse in definitions gleich der Anzahl der Einträge im Array arr ist.
Wenn alle Ergebnisse der callback in definitions Aufruf und übergeben sie die definitions

client[i].onreadystatechange = function() { 
    if (client[i].readyState == 4 && client[i].status == 200) { 
     definitions[arr[i]] = client[i].responseText; 

     if (Object.keys(definitions).length === arr.length) { 
      callback(definitions); 
     } 
    } 
}; 

fiddle

+0

Es gibt ein Problem mit diesem, wenn '' client [i] .readyState == 4 && client [i] .status = = 200'' je wird man falsch sein, dann wird Callback nie aufgerufen. Also muss failCallback oder so ähnlich sein. – sielakos

Verwandte Themen