Как передать результат вызова ajax на последующие вызовы ajax - PullRequest
0 голосов
/ 01 ноября 2019

В настоящее время я пытаюсь использовать несколько вызовов ajax через цепочку ajax, но не уверен в наилучшем подходе, поскольку есть несколько способов сделать это с помощью новых фреймворков, jquery и чистого javascript.

Я бы предпочел сделатьэто с использованием чистого ванильного javascript с учетом того, что нативная разработка на js значительно улучшилась за последние годы, однако, в случае множественных вызовов ajax, я считаю, что многое еще предстоит улучшить, я считаю, что одним из способов будет использованиеобещания? я вижу, что многие сталкиваются с этим вхождением через jquery.

Я был бы очень признателен, если бы коллеги-кодеры могли бы привести свой пример того, как они будут кодировать современный подход цепочечный вызов ajax, зависящий от возвращаемых значений вызова ajax, предшествующих ему.

Хорошо, вкратце, я пытаюсь передать значение первого вызова ajax второму вызову ajax вместе с определением правильного способа выполнения второго вызова ajax.

Нижея добавил код с комментариями:

// Establish functionality on window load:
window.onload = function() {

    'use strict';

    // get product id on load
    var pid = document.getElementById('pid');
    var colorlist = document.getElementById('colorlist');
    var sizelist = document.getElementById('sizelist');

     colorlist.onclick = function(e) { 
    if (typeof e == 'undefined') e = window.event;

    var colorid = e.target.value

    while (sizelist.firstChild) {
    sizelist.removeChild(sizelist.firstChild);
    }

        // 2ND AJAX CALL
        var xhr = getXMLHttpRequestObject();

        xhr.open('GET', '/ajax/get_sizes.php?id=' + encodeURIComponent(pid.value) + '&colorid=' + encodeURIComponent(colorid), true);
        // set header if sending to php
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.send(null);

        // Function to be called when the readyState changes:
        xhr.onreadystatechange = function() {

            // Check the readyState property:
            if (xhr.readyState == 4) {

                    // Check the status code:
                    if ( (xhr.status >= 200 && xhr.status < 300) 
                    || (xhr.status == 304) ) {

                    var sizes = xhr.responseText;
                    var sizes = JSON.parse(sizes);

                    for (var i = 0, num = sizes.length; i < num; i++) {

                    var label = document.createElement('label');

                    label.setAttribute ("for", sizes[i].id);
                    label.classList.add("swatch");
                    label.innerHTML = sizes[i].size;

                    var radio = document.createElement('input');

                    radio.type = "radio";
                    radio.id = sizes[i].id;
                    radio.value = sizes[i].id;
                    radio.name = "sizes";

                    sizelist.appendChild(label);
                    sizelist.appendChild(radio);

                    } //END OF FOR LOOP

                } else { // Status error!
                document.getElementById('output').innerHTML = xhr.statusText;
                }

            } // End of readyState IF.

        }; // End of onreadystatechange anonymous function.
    }; // END OF COLORLIST ONCLICK

    // 1ST AJAX CALL
    var ajax = getXMLHttpRequestObject();

        // Function to be called when the readyState changes:
        ajax.onreadystatechange = function() {

            // Check the readyState property:
            if (ajax.readyState == 4) {

                // Check the status code:
                if ( (ajax.status >= 200 && ajax.status < 300) 
                || (ajax.status == 304) ) {

                    var colors = ajax.responseText;
                    var colors = JSON.parse(colors);

                    for (var i = 0, num = colors.length; i < num; i++) {

                        var label = document.createElement('label');
                        label.setAttribute ("for", colors[i].id);
                        label.classList.add("swatch", colors[i].color);
                        label.innerHTML = colors[i].color;

                        var radio = document.createElement('input');

                        radio.type = "radio";
                        radio.id = colors[i].id;
                        radio.value = colors[i].id;
                        radio.name = "colors";

                        colorlist.appendChild(label);
                        colorlist.appendChild(radio);
                    } // END OF FOR LOOP

                } //END OF STATUS CODE CHECK
                    else { // Status error!
                    document.getElementById('output').innerHTML = ajax.statusText;
                    }

            } // End of onreadyState IF.

        }; // End of onreadystatechange anonymous function.

    ajax.open('GET', '/ajax/get_colors.php?id=' + encodeURIComponent(pid.value), true);
    // set header if sending to php
    ajax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    ajax.send(null); 

}; // End of onload anonymous function.

С уважением, Дэвид

Ответы [ 2 ]

1 голос
/ 01 ноября 2019

Добро пожаловать на SO и спасибо за ваш вопрос. Я сделаю все возможное, чтобы показать вам несколько примеров того, как вы могли бы выполнить свой код таким образом, который может оказаться предпочтительным для вас в качестве решения.

Обратные вызовы

Что такое обратный вызов?

Проще говоря: обратный вызов - это функция, которая должна выполняться после завершения выполнения другой функции - отсюда и название «обратный вызов».

Источникquote

В вашем примере кода вы хотите выполнить как минимум 2 HTTP-запроса друг за другом. Это будет означать, что часть кода должна быть выполнена дважды. Для этого вы можете написать функцию вокруг элемента XMLHTTPRequest, чтобы иметь возможность выполнять ее несколько раз, когда записываете ее только один раз.

Функция ниже имеет два параметра: url и callback. Параметр url - это строка, которая будет вставлена ​​во второй параметр метода xhr.open. Параметр callback будет функцией. Эта функция будет вызвана, когда запрос будет успешно завершен.

function get(url, callback) {
  var xhr = new XMLHTTPRequest();
  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
      if ('function' === typeof callback) {
        callback(xhr.responseText);
      }
    }
  };
  xhr.open('GET', url, true)
  xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  xhr.send();
}

Вот небольшой пример того, как это будет работать. Обратите внимание, что функция обратного вызова имеет параметр с именем data1. Это xhr.responseText, которое мы получили от XMLHTTPRequest. Внутри функции обратного вызова снова вызовите функцию get, чтобы сделать еще один запрос.

get('/ajax1.php', function(data1) {
  // Do something with data1.

  get('/ajax2.php', function(data2) {
    // Do something with data2.
  });

});

Это довольно простой способ сделать запрос после завершения другого.
Но что, если у нас будет 100 запросов друг за другом?

Обещанный XMLHTTPRequest

Объект Promise представляет возможное завершение (или сбой) асинхронной операции и ее итоговое значение.

Источник цитаты

Введите обещания. Пример ниже здесь почти такой же, как пример выше. Только на этот раз мы используем Promise. При звонке get мы сразу же возвращаем Promise. Это обещание будет ждать себя либо resolve, либо reject. В этом случае мы используем resolve только для успешных запросов. Когда запрос завершается, вызывается resolve и начинается цепочка Promise .

function get(url) {
  return new Promise(resolve => {
    var xhr = new XMLHTTPRequest();
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4 && xhr.status === 200) {
        if ('function' === typeof callback) {
          resolve(xhr.responseText);
        }
      }
    };
    xhr.open('GET', url, true)
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xhr.send();
  });
}

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

Внутри функции обратного вызова вызовите следующий запрос.

get('/ajax1.php')
  .then(data1 => {
    // Do something with data1.
    get('/ajax2.php')
      .then(data2 => {
        // Do something with data2.
      });
  });

Fetch

Fetch API предоставляет интерфейс для извлечения ресурсов (в том числе по сети). Это покажется знакомым всем, кто использовал XMLHttpRequest, но новый API предоставляет более мощный и гибкий набор функций.

Источник цитаты

Прежде чем мыМы создали нашу собственную Promise версию XMLHTTPRequest. Но JavaScript развился и получил новые инструменты для работы. fetch похоже на то, как работает наша get функция, но имеет гораздо больше возможностей и опций, чтобы сделать ее более мощнойИ он также использует обещаний !

fetch('/ajax1.php')
  .then(response1 => response1.text())
  .then(data1 => {
    // Do something with data1.

    fetch('/ajax2.php')
      .then(response2 => response2.text())
      .then(data2 => {
        // Do something with data2.
      });

  })
  .catch(error => console.log(error));

Хотя синтаксис then все еще заставляет нас вкладывать функции. Как и раньше, как быть, когда у вас есть 100 функций обратного вызова для вызова? Это будет беспорядок вложений!

Fetch + Async / Await

Теперь это способ решения проблемы вложенности и делает синтаксис более похожим на присвоение простой переменнойв JS. Async / Await является частью современного JavaScript, так что будьте осторожны со старыми браузерами, которые его не поддерживают. Проверьте caniuse на текущую поддержку.

Синтаксис Async / Await работает следующим образом. Создайте функцию с ключевым словом async перед ней. Это будет указывать, как это подразумевает, что здесь будет выполняться асинхронный код. Он также выполняет функцию с асинхронной синхронизацией, прежде чем автоматически вернет Promise.

Внутри асинхронной функции используйте ключевое слово await всякий раз, когда вы вызываете функцию, которая возвращает Promise, например fetch, или нашу собственную функцию get. Это вернет значение resolved без необходимости использования then или функции обратного вызова.

Ключевое слово await также делает код фактически wait , прежде чем продолжитьследующая строка кода. Теперь ваш JS выглядит хорошо и может быть написан с меньшим количеством вложений.

(async function() {

  const response1 = await fetch('/ajax1.php');
  const data1 = await response1.text();
  // Do something with data1.

  const response2 = await fetch('/ajax2.php');
  const data2 = await response2.text();
  // Do something with data1.

}());

Я действительно надеюсь, что это полезно и поможет вам добраться туда, куда вам нужно идти. Если у вас есть какие-либо вопросы относительно вышеизложенного, пожалуйста, дайте мне знать!

Имейте хороший!

0 голосов
/ 01 ноября 2019

Вы можете использовать цепочку Promise, как в примере, приведенном ниже:

.then(function(result) {
    return doSomethingElse(result);
    })
    .then(function(newResult) {
    return doThirdThing(newResult);
    })
    .then(function(finalResult) {
    console.log('Got the final result: ' + finalResult);
    })
    .catch(failureCallback);enter code here

Вы можете ознакомиться с документацией, указанной ниже:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises

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