JavaScript обещает с AJAX - PullRequest
       0

JavaScript обещает с AJAX

0 голосов
/ 02 ноября 2018

Я пытаюсь записать серию запросов AJAX в словарь. Я пытаюсь использовать обещания для этого, однако я либо неправильно пишу синтаксис обещания, либо думаю, что, возможно, происходит то, что функция фактически завершается (цикл завершен, а запросы 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);
});

Есть ли способ "почувствовать", когда вернулись все запросы XMLHTTP?

Ответы [ 2 ]

0 голосов
/ 02 ноября 2018

@ Ответ Рафаэля сработает, но он мало освещает происходящее, так как вы пытаетесь ухватить концепцию Обещаний и написать ее самостоятельно.

В принципе, я думаю, что ваш подход имеет два ошибочных шага: 1. создание одного Promise, который обрабатывает вызовы для всех ваших произвольных списков «activeMachines», и 2. размещение вашего вызова resolve() в неправильном месте.

Обычно обещание выглядит так:

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, вы должны обобщить его, чтобы он мог использоваться повторно и инкапсулировал только один сетевой запрос. Таким образом, вы можете запустить несколько асинхронных Обещаний, подождать, пока они все разрешатся, и , а затем сделать что-то.

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

API fetch() великолепен, и вы должны научиться использовать его также - но только после того, как вы поймете теорию и практику того, как на самом деле работают Promises. :)

0 голосов
/ 02 ноября 2018

Вот пример Fetch API, который по умолчанию использует Promises:

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

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...