JavaScript承诺可使用AJAX

时间:2018-11-01 23:20:28

标签: javascript ajax

我正在尝试将一系列AJAX请求写入字典。 我正在尝试为此使用诺言,但是我要么写了不正确的诺言语法,要么我认为可能正在发生的是该函数实际上已经完成(for循环已经完成,并且发送了AJAX请求),但是AJAX请求仍然存在没有退货。因此,这仍然返回一个空字典。

let dict = {};
let activeMachines = ["41", "42", "43"];
let dataPromise = new Promise (function (resolve, reject){
  for(let i = 0; i < activeMachines.length; i++){
  let machineID = activeMachines[i]
  let getAPIData = new XMLHttpRequest();
  let url = 'http://127.0.0.1:8000/processes/apidata/' +machineID + '/';
  getAPIData.open('GET', url);
  getAPIData.send();
  getAPIData.onload = function(){
    let APIData = JSON.parse(getAPIData.responseText);
    dict['machine_' + machineID] = APIData[0].author_id;
    dict['temp' + machineID] = APIData[0].tempData; //get value
    dict['humid' + machineID] = APIData[0].humidData;
    timeValue = String((APIData[0].dateTime));
    dict['time' + machineID] = new Date(timeValue);
    console.log("done");
  }
}
resolve();
});

dataPromise.then(function() {
  console.log(dict);
});

所有XMLHTTPRequest返回后,是否有一种“感知”方法?

2 个答案:

答案 0 :(得分:3)

以下是默认情况下使用Promises的Fetch API示例:

let m_ids = [1,2,3,4];
let forks = m_ids.map(m => fetch(`http://127.0.0.1:8000/processes/apidata/${m}`));
let joined = Promise.all(forks);

joined
    .then(files => console.log('all done', files))
    .catch(error => console.error(error));

我希望这会有所帮助!

答案 1 :(得分:2)

@Rafael的答案会起作用,但是它并不能说明什么地方出了问题,因为您正试图理解Promises的概念并自己编写。

从根本上讲,我认为您的方法有两个错误步骤:1.创建一个Promise,该Promise处理对您的所有“ activeMachines”任意列表的调用,并且2.将resolve()调用放在错误的位置。

通常,Promise如下:

const myPromise = new Promise(function(resolve, reject) {
  doSomeAsyncWork(function(result) {
    // Some kind of async call with a callback function or somesuch...
    resolve(result);
  });
}).then(data => {
  // Do something with the final result
  console.log(data);
});

您可以使用setTimeout()模拟某种任意的异步工作:

const myPromise = new Promise(function(resolve, reject) {
  // Resolve with "Done!" after 5 seconds
  setTimeout(() => {
    resolve("Done!");
  }, 5000);
}).then(data => {
  console.log(data); // "Done!"
});

但是,您的原始代码将resolve()调用放在一个奇怪的地方,甚至没有传递任何数据。看起来有点像这样:

const myPromise = new Promise(function(resolve, reject) {
  // Resolve with "Done!" after 5 seconds
  setTimeout(() => {
    // Doing some work here instead of resolving...
  }, 5000);
  resolve();
}).then(data => {
  console.log(data); // This would be "undefined"
});

您在原始代码中执行console.log("done");的位置实际上就是您应该执行resolve(someData);的位置!

您还尝试在Promise的异步功能内进行副作用工作,这确实很奇怪,与Promise的工作原理相反。应许的诺言将消失并完成其异步工作,然后然后使用生成的数据进行解析-实际上是使用.then()链。

此外,您应该对其进行概括,以使其可重用并且仅封装单个网络请求,而不是在Promise中进行多个异步调用。这样,您可以触发多个异步Promise,等待它们全部解决,然后然后做些事情。

const activeMachines = ["41", "42", "43"];

// Make a reusable function that returns a single Promise
function fetchAPI(num) {
  return new Promise(function(resolve, reject) {
    const getAPIData = new XMLHttpRequest();
    const url = "http://127.0.0.1:8000/processes/apidata/" + num + "/";
    getAPIData.open("GET", url);
    getAPIData.send();
    getAPIData.onload = function() {
      const APIData = JSON.parse(getAPIData.responseText);
      const resolveData = {};
      resolveData["machine_" + num] = APIData[0].author_id;
      resolveData["temp" + num] = APIData[0].tempData; //get value
      resolveData["humid" + num] = APIData[0].humidData;
      timeValue = String(APIData[0].dateTime);
      resolveData["time" + num] = new Date(timeValue);
      resolve(resolveData);
    };
  });
}

// Promise.all() will resolve once all Promises in its array have also resolved
Promise.all(
  activeMachines.map(ea => {
    return fetchAPI(ea);
  })
).then(data => {
  // All of your network Promises have completed!
  // The value of "data" here will be an array of all your network results
});

fetch() API很棒,您也应该学习使用它-但只有在您了解Promises实际操作背后的理论和实践之后,才应该使用它。 :)