Promise в Ajax-запросах

Последнее обновление: 10.04.2018

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

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

Инкапсулируем асинхронный запрос в объект Promise:

function get(url) {
  return new Promise(function(succeed, fail) {
    var request = new XMLHttpRequest();
    request.open("GET", url, true);
    request.addEventListener("load", function() {
      if (request.status < 400)
        succeed(request.response);
      else
        fail(new Error("Request failed: " + request.statusText));
    });
    request.addEventListener("error", function() {
      fail(new Error("Network error"));
    });
    request.send();
  });
}

Метод get получает в качестве параметра адрес ресурса сервера и возвращает объект Promise. Конструктор Promise в качестве параметра принимает функцию обратного вызова, которая в свою очередь принимает два параметра - две функции: одна выполняется при успешной обработке запроса, а вторая - при неудачной.

Допустим, на сервере будет размещен файл users.json со следующим содержимым:

[
	{
		"name": "Tom",
		"age": 34
	}, {
		"name": "Sam",
		"age": 32
	}, {
		"name": "Bob",
		"age": 26
	}
]

Теперь вызовем метод get для осуществления запроса к серверу:

get("http://localhost:8080/users.json").then(function(text) {
  console.log(text);
}, function(error) {
  console.log("Error!!!");
  console.log(error);
});

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

get("http://localhost:8080/users.json").then(function(response) {
	console.log(response);
	return JSON.parse(response);
}).then(function(data) {
	console.log(data[0]);
});

В данном случае функция в первом вызове метода then получает ответ сервера и возвращает распарсенные данные в виде массива с помощью функции JSON.parse().

Функция во втором вызове then получает эти распарсенные данные, то есть массив, в виде параметра (возвращаемое значение предудыщего then является параметром для последующего then). Затем первый элемент массива выводится на консоль.

Для обработки ошибок мы мы можем использовать метод catch(), в который передается функция обработки ошибок:

get("http://localhost:8080/users.jsn").then(function(response) {
	console.log(response);
	return JSON.parse(response);
}).then(function(data) {
	console.log(data[0]);
}).catch(function(error){
	console.log("Error!!!");
	console.log(error);
});

Подобным образом через Promise можно было бы отправлять данные на сервер:

function post(url, requestuestBody) {
  return new Promise(function(succeed, fail) {
    var request = new XMLHttpRequest();
    request.open("POST", url, true);
	request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    request.addEventListener("load", function() {
      if (request.status < 400)
        succeed(request.responseText);
      else
        fail(new Error("Request failed: " + request.statusText));
    });
    request.addEventListener("error", function() {
      fail(new Error("Network error"));
    });
    request.send(requestuestBody);
  });
}

var user = {
	name: "Tom&Tim",
	age: 23
};
// данные для отправки
var params = "name=" + user.name + "&age="+user.age;

post("http://localhost:8080/postdata.php", params).then(function(text) {
  console.log(text);
}, function(error) {
  console.log(error);
});
Помощь сайту
WebMoney
  • P378451176208
  • Z280152397659
ЮMoney/Яндекс-Деньги
  • 410011174743222
PayPal
  • metanit22@mail.ru
Перевод на карту
  • Номер карты: 4048415020898850