Применение Promise для инкапсуляции практики Ajax

внешний интерфейс Promise Ajax axios

Свинец: Axios часто используется в проекте, но есть время, чтобы заставить меня инкапсулировать Ajax в форму Axios, и я не писал ее. Кажется, что он все еще не доступен на поверхности использованного. Это не очень трудно изучить обещание, ключ состоит в том, чтобы освоить спецификацию обещания A + и обещание.
Давайте посмотрим, как реализованы axios.

Часть Axios анализа исходного кода:

axiosпредставление о себе:Promise based HTTP client for the browser and node.jsкоторый:
Я, axios, являюсь HTTP-клиентом на основе Promise для браузеров и node.js.

Далее основное внимание уделяется части ajax, которую я хочу понять.

модуль адаптеров в axios

The modules under adapters/ are modules that handle dispatching a request and settling a returned Promise once a response is received.
Этот модуль в основном обрабатывает запросы на отправку и обрабатывает возвращенный промис после получения ответа.

Посмотреть в исходном коде:axios/lib/adapters/xhr.jsВот этот отрывок бросается в глаза:

module.exports = function xhrAdapter(config) {
 return new Promise(function dispatchXhrRequest(resolve, reject) {
 })
}

Найден обещанный базовый лагерь! Продолжайте смотреть исходный код, следующим шагом будет работа с ajax внутри Promise.open, onreadystatechange, sendНесколько реализаций, по-прежнему следуйте правилам, выберите их и посмотрите:

  // =>...omit config...
  // step1=>
  var request = new XMLHttpRequest();
  // step2=>
  request.open(config.method.toUpperCase(), buildURL(config.url, config.params, config.paramsSerializer), true);
  // step3=>
  request.onreadystatechange = function handleLoad() {
    if (!request || request.readyState !== 4) {
      return;
    }
  
    // The request errored out and we didn't get a response, this will be
    // handled by onerror instead
    // With one exception: request that using file: protocol, most browsers
    // will return status as 0 even though it's a successful request
    if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) {
      return;
    }
  
    // Prepare the response
    var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null;
    var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response;
    var response = {
      data: responseData,
      status: request.status,
      statusText: request.statusText,
      headers: responseHeaders,
      config: config,
      request: request
    };
  
    settle(resolve, reject, response);
    // Clean up request
    request = null;
  };
  // =>...omit handle process...
  // step4=>
  request.send(requestData);

Вышеупомянутое является просто реализацией ajax, но ядро, а затем цепочка вызовов не реализовано, реальная реализацияaxios/lib/core/settle.jsМетод расчета ниже:

/**
* Resolve or reject a Promise based on response status.
*
* @param {Function} resolve A function that resolves the promise.
* @param {Function} reject A function that rejects the promise.
* @param {object} response The response.
*/
module.exports = function settle(resolve, reject, response) {
 var validateStatus = response.config.validateStatus;
 if (!validateStatus || validateStatus(response.status)) {
   resolve(response);
 } else {
   reject(createError(
     'Request failed with status code ' + response.status,
     response.config,
     null,
     response.request,
     response
   ));
 }
};

Ключевойresolveа такжеrejectПосле заселения согласно регламенту (Обещание A+ Спецификация)

Обещание должно предоставлять метод then для доступа к его текущему или конечному значению или причине.

В это время, по словамpromise.then(onFulfilled, onRejected)и используйте два метода для обработки возврата. Вышеупомянутое в основном реализовало функцию ajax.

Следующее инкапсулирует собственный promise_ajax, основанный на идее axios.

Первоначально реализуйте свой собственный P_ajax

function pajax({
    url= null,
	method = 'GET',
	dataType = 'JSON',
	async = true}){
	return new Promise((resolve, reject) => {
		let xhr = new XMLHttpRequest()
		xhr.open(method, url, async)
		xhr.responseType = dataType
		xhr.onreadystatechange = () => {
			if(!/^[23]\d{2}$/.test(xhr.status)) return
			if(xhr.readyState === 4) {
				let result = xhr.responseText
				resolve(result)
			}
		}
		xhr.onerror = (err) => {
			reject(err)
		}
		xhr.send()
	})
}

Формат JSON вызывается по умолчанию, и тест проходит успешно.

ajax({
    url:'./test.json',
    method: 'get'
}).then((result)=>{
    console.log(result)
},(err)=>{

})

Оптимизация обновления

Различная обработка для разных типов запросов и типов файлов

  • Добавьте, чтобы судить о типе запроса, когда запрос получен, выполните другую обработку для кеша. Когда кеш имеет значение false, кеш не устанавливается, и самое простое решение — добавить _***, *** — это случайное число.
// 判断请求类型是否为GET
let isGet = /^(GET|DELETE|HEAD)$/i.test(method)
// 判断url有没有?,有的话就添加&
let symbol = url.indexOf('?')>-1 ? '&' : '?'
// GET系列请求才处理cache
if(isGet){
    !cache ? url+= `${symbol}_${Math.random()}`: null
}
  • Обработка результата по-разному в зависимости от типа возвращаемого значения
    let result = xhr.responseText
    // 根据dataType即不同的文件类型,对返回的内容做处理 
    switch(this.dataType.toUpperCase()){
        case 'TEXT':
        case 'HTML':
            break;
        case 'JSON':
            result = JSON.parse(result)
            break;
        case 'XML':
            result = xhr.responseXML
    }   
  • данные обработки Когда данные являются объектом, они преобразуются в строку, а в запрос на получение передаются параметры
   function formatData(data){
       if(Object.prototype.toString.call(data)==='[object Object]'){
           let obj = data
           let str = ''
           for(let key in obj){
               if(obj.hasOwnProperty(key)){
                   str+=`${key}=${obj[key]}&`
               }
           }
           // 去掉最后多加的&
           str = str.replace(/&$/g,'')
           return str
       }
   }
   if(data !== null){
       data = formatData(data)
       if(isGet){
           url += symbol + data
           data = null
       }
   }

Результат простого теста:

pajax({
        url:'./test.json',
        method: 'get',
        cache: false,
        data:{
    	    name:'jyn',
            age:20
        }
	}).then((result)=>{
	    console.log(result)
    },(err)=>{
        console.log(err)
    })

Текущий результат:Request URL: http://localhost:63342/june/HTTP_AJAX/test.json?_0.6717612341262227?name=jyn&age=20в настоящее время надежный иthenМетод также может получить данные файла. Когда для кеша установлено значение false, каждое обновление равно 200, а 304 не выполняется, и функция работает нормально.

Выше показан простой ajax, основанный на Promise!

Author: Yanni Jia
Прозвище: Очень кролик
Ссылка: исходный код axios: https://github.com/axios/axios