как дождаться результата http-запроса (синхронный http-запрос, http-запрос как обещание)

#javascript #typescript #asynchronous #promise

#javascript #typescript #асинхронный #обещание

Вопрос:

У меня есть служба typescript, которая загружает базовые данные по htpp-запросам с сервера. Есть несколько запросов для нескольких данных, расположенных в порядке от независимых данных к данным в зависимости от данных, для которых загрузка была начата ранее. Из-за асинхронных http-запросов не гарантируется, что загрузка данных по запросу (например, клиенты в следующем примере) завершена, или начинается загрузка данных, которые зависят от него (например, устройства в следующем примере), и я не могу ссылаться на загружаемые устройства на загруженных клиентов. Но я хотел бы, чтобы обработка зависимых данных (устройств) начиналась после завершения загрузки данных, переданных (клиентам). Я думаю, мне нужно использовать promises, но как реализовать concrete в следующей ситуации с кодом?

 export class BaseDataService
{
  customers: Customer[] = new Array();
  devices: Device[] = new Array();

  // Loads the base data arranged in order from undependent data to data dependent data  
  loadBaseData() {
    this.loadCustomers();
    // this operation should be started after loading customers has finished (the response json 
    //is parsed to an array of customers at set to the instance variable of this service class)
    this.loadDevices();
  }

  // Loads the customers and adds them to the collection of customers.
  // Also puts the response json string of the customers to the local storage.
  loadCustomers() {
    console.log("Load customers");

    var requestURL = 'https://myurl/kunden_json_user_extern.php';
    var auth = window.localStorage.getItem('auth');
    var requestparam = "auth=" auth;

    var request = new XMLHttpRequest();
    request.open('POST', requestURL);
    request.setRequestHeader("content-type", "application/x-www-form-urlencoded");
    request.send(requestparam);

    request.onload = () => {
      if (request.status === 200){ 
        console.log("Load customers response");
        // gets as json string with the customers array
        var response = request.response;
        // parses the json string of customers to an array of customers objects
        this.customers = this.parseCustomers(response);         
        console.log("Load customers complete");
    }
    else if (request.status === 401){
      alert("unautorized");              
    }
    else {
      // lade saved items aus local storage
      alert("unerwarteter Fehler");
    }
  }
}

// Loads the devices and adds them to the collection of devices.
// Also puts the response json string of the devices to the local storage.
loadDevices() {
  console.log("Load devices");

  var requestURL = 'https://myurl/geraete_json_user_extern.php';
  var auth = window.localStorage.getItem('auth');
  var requestparam = "auth=" auth;

  var request = new XMLHttpRequest();
  request.open('POST', requestURL);
  request.setRequestHeader("content-type", "application/x-www-form-urlencoded");
  request.send(requestparam);

  request.onload = () => {
    if (request.status === 200){ 
      console.log("Load devices response");
      var response = request.response;          
      window.localStorage.setItem('devicesresponse', response);
      this.devices = this.parseDevices(response);          
      console.log("Load devices complete");
    }
    else if (request.status === 401){
      alert("unautorized");              
    }
    else {
      // lade saved items aus local storage
      alert("unerwarteter Fehler");
    }
  }
}


// Parses a json string formatted like the response of customers to an array of customers
parseCustomers(customersjson: string)
{
  let customerarray = JSON.parse(customersjson);
  let customers: Customer[] = [];
  for (let i = 0; i < customerarray.length; i  ) {
      let customer: Customer = new Customer();
      customer.setId(customerarray[i]['id']);
      customer.setName(customerarray[i]['name']);
      customer.setPlace(customerarray[i]['ort']);
      customer.setStreet(customerarray[i]['strasse']);

      customers[i] = customer;
  }
  return customers;
}

 // Parses a json string formatted like the response of devices to an array of devices
 parseDevices(devicesjson: string)
 {
   let devicearray = JSON.parse(devicesjson);
   let devices: Device[] = [];
   for (let i = 0; i < devicearray.length; i  ) {
      let device = new Device();
      device.setId(devicearray[i]['geraet_id']);
      device.setSerialnumber(devicearray[i]['geraet_seriennummer']);
      device.setDescription(devicearray[i]['geraet_bezeichnung']);
      // here i would like to refer to a prevoiusly loaded customer
      //device.setCustomer(this.baseDataService.getCustomer(devicearray[i]['geraet_kunde_id']); 
      device.setLocation(devicearray[i]['geraet_standort']);

      devices[i] = device;
     }
    return devices;
  }
}
  

Комментарии:

1. Почему бы не использовать что-то вроде axios, которое оборачивает это в обещание для вас?

2. Пожалуйста, прекратите использовать функции 20-летней давности. Вместо этого используйте выборку

3. Ответ на вашу проблему заключается в использовании async / await

4. Дайте мне знать, сработал ли мой ответ на синхронный вызов ajax!

Ответ №1:

Вы можете передать обратный вызов любой из функций ‘load’, чтобы:

Этот код:

 loadBaseData() {
    this.loadCustomers();
    // this operation should be started after loading customers has finished (the response json 
    //is parsed to an array of customers at set to the instance variable of this service class)
    this.loadDevices();
  }
  

Измените этот код:

 loadBaseData() {
    this.loadCustomers(() => {
        this.loadDevices();
    });
  }
  

И вызовите этот обратный вызов внутри вашего request.onload :

 // Loads the customers and adds them to the collection of customers.
// Also puts the response json string of the customers to the local storage.
loadCustomers(callback) { // <--- this is a callback passed to function
    // ... many code here ...
    request.onload = () => {
        // ... many code here ...
        console.log("Load customers complete");
        if (typeof callback === 'function') callback(); // <--- here we call it
    }
// ... many code here ...
  

Комментарии:

1. Я думаю, что передача обратного вызова не была бы хорошей. это всего лишь отрывок, и было бы загружено гораздо больше данных, передача обратного вызова функции загрузки, которой передается обратный вызов и так далее, Привела бы к аду вызовов.

2. выполнение синхронного вызова xhr.open(«»post, url, false) работает, спасибо

3. я знаю, что использование выборки и async / await было бы самым лучшим и современным решением. но я новичок в javascript и не понимаю использования promise. Как бы я должен был реализовать это с использованием promise и async / await

Ответ №2:

Вы можете выполнить synchronous ajax вызов, подобный приведенному ниже. Таким образом, он ожидает ответа перед выполнением следующих инструкций.

 xhr.open("POST",url,false);