2017-08-15 1 views
1

Ich habe Probleme mit fetch(), die ich verwende, um JSON abzurufen. I denke, das Problem ist, dass der Code abgeschlossen ist und versucht, auf das Array vor dem fetch() hat tatsächlich "heruntergeladen" und verarbeitet es. Ich habe anfangs eine einfachere Version geschrieben, die zu dem gleichen Problem führte; der Großteil des Codes hier is from Google Developers.Javascript: Wie sicherzustellen, dass fetch() beendet ist, bevor Sie die Daten verwenden?

Wie unten gezeigt (SetTimeout enthalten nur das Problem zu demonstrieren) ich unterschiedliche Ergebnisse erhalten, wenn zweimal die gleiche Array-Zugriff auf eine Sekunde auseinander:

dataResultArray = requestJSONResult(searchString); 

console.log(dataResultArray);   // logs '[]' 
console.log(dataResultArray.length); // logs '0' 

setTimeout(function(){ 
    console.log(dataResultArray);   // logs the actual JSON array contents 
    console.log(dataResultArray.length); // logs the real array length 
}, 1000); 


function requestJSONResult(searchString) { 
    var tempArray = [] 

    fetch(`/search/?term=${searchString}`) 
    .then(status) 
    .then(json) 
    .then(function(data) { 
     tempArray.push(...data) 
    }).catch(function(error) { 
    console.log('Request failed', error); 
    }); 

    return tempArray; 
} 

function status(response) { 
    if (response.status >= 200 && response.status < 300) { 
    return Promise.resolve(response) 
    } else { 
    return Promise.reject(new Error(response.statusText)) 
    } 
} 

function json(response) { 
    return response.json() 
} 
+0

Google Javascript verspricht und/oder Rückrufe – yBrodsky

+0

Sie müssen Versprechen richtig zu verwenden. Geben Sie das Versprechen Ihrer Funktion zurück und fügen Sie einen 'then'-Handler hinzu, anstatt zu versuchen, das Ergebnis in ein Array zu pushen. Es gibt keine Möglichkeit, die zuverlässig funktioniert. – Amy

+0

Sobald Sie Versprechungen verwenden, bleiben Sie bei 'then'-Callbacks, selbst in Ihrem Hauptskript, das diese Funktionen aufruft. Sie können dort nur auf die asynchron abgerufenen Daten zugreifen. – trincot

Antwort

2

Es scheint, Sie versuchen, Ihren asynchronen Code synchron zu machen, die ist keine gute Idee.

Rückkehr einfach das Versprechen von holen die Daten abzurufen, etwa so:

function requestJSONResult(searchString) { 
    return fetch(`/search/?term=${searchString}`) 
    .then(status) 
    .then(json); 
} 

function status(response) { 
    if (response.status >= 200 && response.status < 300) { 
    return Promise.resolve(response) 
    } else { 
    return Promise.reject(new Error(response.statusText)) 
    } 
} 

function json(response) { 
    return response.json() 
} 


requestJSONResult(searchString) 
    .then(function(data) { 
    console.log(data); 
    console.log(data.length); 
    }) 
    .catch(function(error) { 
    console.log('Request failed', error); 
    }); 

Jetzt ist Ihre requestJSONResult gibt ein Versprechen, das entweder lösen könnte oder ablehnen, so kann jeder Anrufer für diese Ereignisse warten.

1

Denken Sie daran, dass ich dies nicht getestet habe. Sie müssen Versprechen durchweg verwenden. Der Versuch, asynchronen Code zu erzwingen, ist nicht zuverlässig, wie Sie festgestellt haben.

function status(response) { 
    if (response.status >= 200 && response.status < 300) { 
    return Promise.resolve(response) 
    } else { 
    return Promise.reject(new Error(response.statusText)) 
    } 
} 

Unsere Linie 2 von requestJSONResult: return fetch(....). Wir geben das Versprechen von der Funktion zurück.

function requestJSONResult(searchString) { 
    return fetch(`/search/?term=${searchString}`) 
     .then(status) 
     .then(function(response) { 
      return response.json(); 
     }) 
     .catch(function(error) { 
      console.log('Request failed', error); 
     }); 
} 

requestJSONResult(searchString) 
    .then(function(result) { 
     console.log(result); 
    }); 
Verwandte Themen