Javascript: 如何确保在使用数据之前fetch()已经完成?

Javascript: how to ensure that fetch() has finished before using the data?

我正在努力使用 fetch(),我正在使用它来检索 JSON。我 认为 问题是代码在 fetch() 实际下载并处理之前完成并尝试 'act' 数组。我最初写了一个更简单的版本,导致了同样的问题;此处的大部分代码 is from Google Developers.

如下所示(仅包括 setTimeout 以演示问题)我两次访问同一个数组时得到不同的结果,相隔一秒:

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()  
}

看来您正在尝试使异步代码同步,这不是一个好主意。

只是 return 从 fetch 中获取数据的承诺,如下所示:

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);
  });

现在您的 requestJSONResult return 是一个可以解决或拒绝的承诺,因此任何调用者都可以等待这些事件。

请记住,我还没有对此进行测试。您需要始终使用承诺。正如您所发现的,尝试强制异步代码同步是不可靠的。

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

注意 requestJSONResult 的第 2 行:return fetch(....)。我们 return 函数的承诺。

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); 
    });