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

时间:2017-08-15 20:21:57

标签: javascript asynchronous fetch

我正在努力使用fetch(),我正在使用它来检索JSON。我认为问题在于代码完成并试图“行动”。在fetch()实际下载并处理它之前的数组上。我最初写了一个更简单的版本,导致了同样的问题;这里的大部分代码都是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()  
}

2 个答案:

答案 0 :(得分:2)

看来你正试图使你的异步代码同步,这不是一个好主意。

只需从fetch返回promise即可检索数据:

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会返回一个可以解决或拒绝的承诺,这样任何调用者都可以等待这些事件。

答案 1 :(得分:1)

请记住,我还没有对此进行过测试。你需要在整个过程中使用承诺。正如您所发现的那样,尝试强制异步代码同步并不可靠。

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(....)。我们从函数中返回承诺。

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