Maison  >  Article  >  interface Web  >  Comment gérer le délai d'attente de la demande Vue Axios

Comment gérer le délai d'attente de la demande Vue Axios

php中世界最好的语言
php中世界最好的语言original
2018-04-08 14:48:043329parcourir

Cette fois, je vais vous montrer comment gérer le délai d'expiration de la requête vue axios. Quelles sont les précautions lors de la gestion du délai d'expiration de la requête vue axios. Ce qui suit est un cas pratique, jetons un coup d'œil.

Depuis que j'utilise Vue2, j'utilise le plug-in axios officiellement recommandé pour appeler l'API. Pendant l'utilisation, si le serveur ou le réseau est instable et que des paquets sont abandonnés, comment devez-vous gérer cela ? avec vous ce que j'ai vécu.

Raison spécifique

Récemment, l'entreprise travaille sur un projet L'interface de données côté serveur utilise la sortie API de Php, qui. est parfois appelé Le processus échouera et les en-têtes provisoires sont affichés dans Google Chrome.

D'après les solutions proposées par le moteur de recherche, mon problème ne peut pas être résolu

Récemment, j'étudie le concept de programmation de développement AOP, qui est. dans les instructions de développement axios Les intercepteurs mentionnés (axios.Interceptors) devraient être ce mécanisme, qui réduit le couplage de code, améliore la réutilisabilité du programme et améliore l'efficacité du développement.

Solution 1 avec des pièges

Mon expérience est limitée et je pense que la seule chose que je peux faire est de faire une nouvelle demande après les axios la demande expire. En étudiant les instructions d'utilisation d'axios, définissez un timeout = 6000 pour celui-ci

axios.defaults.timeout = 6000;

puis ajoutez un coupe-colonne

// Add a request interceptor
axios.interceptors.request.use(function (config) {
 // Do something before request is sent
 return config;
 }, function (error) {
 // Do something with request error
 return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use(function (response) {
 // Do something with response data
 return response;
 }, function (error) {
 // Do something with response error
 return Promise.reject(error);
});

Le rôle de ce coupe-colonne est si la demande. expire. , l'intercepteur de colonne peut capturer les informations, puis passer à l'étape suivante, c'est-à-dire que je souhaite redemander.

Voici les demandes de données de page pertinentes.

this.$axios.get(url, {params:{load:'noload'}}).then(function (response) {
	//dosomething();
}).catch(error => {
	//超时之后在这里捕抓错误信息.
	if (error.response) {
		console.log('error.response')
		console.log(error.response);
	} else if (error.request) {
		console.log(error.request)
		console.log('error.request')
		if(error.request.readyState == 4 && error.request.status == 0){
			//我在这里重新请求
		}
	} else {
		console.log('Error', error.message);
	}
	console.log(error.config);
});

Après le délai d'attente, une erreur Uncaught (in promise) : timeout of xxx ms dépassé sera signalée.

Dans catch, il renvoie une erreur error.request, donc la fonction de nouvelle tentative est effectuée ici Après le test, la fonction de re-demande peut être réalisée bien que cela soit possible. implémente la fonction de redemande après expiration du délai, mais cela est très gênant. Cela nécessite de définir la redemande dans chaque page qui demande l'API.

Regardez ci-dessus, mon projet contient des dizaines de fichiers .vue si chaque page doit définir le délai d'attente et la fonction de nouvelle demande, alors je deviendrai fou

.

Et il y a un bug sérieux dans ce mécanisme, c'est-à-dire que lorsque le lien demandé échoue ou n'est pas accessible normalement pour d'autres raisons, ce mécanisme échoue, il n'attendra pas les 6 secondes que j'ai définies et il continuera. Lors du brossage, des dizaines de requêtes par seconde peuvent facilement faire tomber le serveur. Veuillez voir l'image ci-dessous. En un clin d'œil, il demande 146 fois.

Solution 2 avec pièges

Après étude du code source d'axios, après timeout, L'erreur le message est intercepté dans l'intercepteur axios.interceptors.response, et error.code = "ECONNABORTED", le lien spécifique

https://github.com/axios/axios/blob/26b06391f831ef98606ec0ed406d2be1742e9850/lib/ adapters/ xhr.js#L95-L101

// Handle timeout
 request.ontimeout = function handleTimeout() {
  reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED',
  request));
  // Clean up request
  request = null;
 };

Donc, ma solution pour la récupération globale du délai d'attente est comme ceci.

axios.interceptors.response.use(function(response){
....
}, function(error){
	var originalRequest = error.config;
	if(error.code == 'ECONNABORTED' && error.message.indexOf('timeout')!=-1 && !originalRequest._retry){
			originalRequest._retry = true
			return axios.request(originalRequest);
	}
});

Cette méthode peut également implémenter de nouvelles requêtes, mais il y a deux problèmes : 1. Elle ne redemande qu'une seule fois. Si elle expire à nouveau, elle s'arrête et ne demandera plus. Le deuxième problème est que je fais de nombreuses opérations sur chaque page avec des requêtes de données, comme des opérations après this.$axios.get(url).then.

Solution parfaite

En programmation AOP, ce dont j'ai besoin est une fonction globale pour la nouvelle demande de délai d'attente, à faire dans axios.Interceptors Après avoir travaillé dur, j'ai cherché des solutions auprès d'autres personnes pour le problème axios sur github, et j'ai finalement trouvé une solution parfaite, qui est celle ci-dessous.

https://github.com/axios/axios/issues/164#issuecomment -327837467

//在main.js设置全局的请求次数,请求的间隙
axios.defaults.retry = 4;
axios.defaults.retryDelay = 1000;
axios.interceptors.response.use(undefined, function axiosRetryInterceptor(err) {
 var config = err.config;
 // If config does not exist or the retry option is not set, reject
 if(!config || !config.retry) return Promise.reject(err);
 // Set the variable for keeping track of the retry count
 config.retryCount = config.retryCount || 0;
 // Check if we've maxed out the total number of retries
 if(config.retryCount >= config.retry) {
  // Reject with the error
  return Promise.reject(err);
 }
 // Increase the retry count
 config.retryCount += 1;
 // Create new promise to handle exponential backoff
 var backoff = new Promise(function(resolve) {
  setTimeout(function() {
   resolve();
  }, config.retryDelay || 1);
 });
 // Return the promise in which recalls axios to retry the request
 return backoff.then(function() {
  return axios(config);
 });
});

L'autre get et get de this.$axios pour des dizaines de pages .vue Le La méthode post n’a pas du tout besoin de modifier son code.

在这个过程中,谢谢jooger给予大量的技术支持,这是他的个人信息  https://github.com/jo0ger  , 谢谢。

以下是我做的一个试验。。把axios.defaults.retryDelay = 500, 请求 www.facebook.com

如有更好的建议,请告诉我,谢谢。

补充:

axios基本用法

vue更新到2.0之后,作者就宣告不再对vue-resource更新,而是推荐的axios,前一段时间用了一下,现在说一下它的基本用法。

首先就是引入axios,如果你使用es6,只需要安装axios模块之后

import axios from 'axios';
//安装方法
npm install axios
//或
bower install axios

当然也可以用script引入

axios提供了一下几种请求方式

axios.request(config)
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]])

这里的config是对一些基本信息的配置,比如请求头,baseURL,当然这里提供了一些比较方便配置项

//config
import Qs from 'qs'
{
 //请求的接口,在请求的时候,如axios.get(url,config);这里的url会覆盖掉config中的url
 url: '/user',
 // 请求方法同上
 method: 'get', // default
 // 基础url前缀
 baseURL: 'https://some-domain.com/api/',
  
    
 transformRequest: [function (data) {
  // 这里可以在发送请求之前对请求数据做处理,比如form-data格式化等,这里可以使用开头引入的Qs(这个模块在安装axios的时候就已经安装了,不需要另外安装)
  data = Qs.stringify({});
  return data;
 }],
 transformResponse: [function (data) {
  // 这里提前处理返回的数据
  return data;
 }],
 // 请求头信息
 headers: {'X-Requested-With': 'XMLHttpRequest'},
 //parameter参数
 params: {
  ID: 12345
 },
 //post参数,使用axios.post(url,{},config);如果没有额外的也必须要用一个空对象,否则会报错
 data: {
  firstName: 'Fred'
 },
 //设置超时时间
 timeout: 1000,
 //返回数据类型
 responseType: 'json', // default
}

有了配置文件,我们就可以减少很多额外的处理代码也更优美,直接使用

axios.post(url,{},config)
  .then(function(res){
    console.log(res);
  })
  .catch(function(err){
    console.log(err);
  })
//axios请求返回的也是一个promise,跟踪错误只需要在最后加一个catch就可以了。
//下面是关于同时发起多个请求时的处理
axios.all([get1(), get2()])
 .then(axios.spread(function (res1, res2) {
  // 只有两个请求都完成才会成功,否则会被catch捕获
 }));

最后还是说一下配置项,上面讲的是额外配置,如果你不想另外写也可以直接配置全局

axios.defaults.baseURL = 'https://api.example.com';
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
//当然还可以这么配置
var instance = axios.create({
 baseURL: 'https://api.example.com'
});

本文只是介绍基本的用法,详细看官方文档https://github.com/axios

我写的两个例子:

使用vue2.0+mintUI+axios+vue-router: https://github.com/Stevenzwzhai/vue-mobile-application

使用vue2.0+elementUI+axios+vue-router: https://github.com/Stevenzwzhai/vue2.0-elementUI-axios-vueRouter, 之前由于没做后端接口,所以运行没数据,现在加了mockjs来返回一些数据,以便于参考。

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

webpack里脚手架优化的实现方法

Vue项目应该怎么分环境打包

webpack-dev-server的使用步奏

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn