1. 程式人生 > >vue路由切換終止請求

vue路由切換終止請求

ons 服務 reac func thrown 求和 gen [] ajax

問題:

在SPA模式開發當中,比如VUE ,當前路由切換的時候如何終止正在發生的異步請求呢,

結果:

假如請求超時並且有設定超時時間。有一堆的異步請求在執行,當用戶切換到另一個頁面,這些請求還未終止,並且當服務器響應之後,反饋的結果不是當前頁面所期待的。最終會誤導用戶造成一些不必要的結果。也給web 造成性能問題。

解決方案:

把執行的請求存入隊列,當路由切換的時候終止隊列裏的異步請求。

首先搞一棵樹來存儲請求隊列

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let store = new Vuex.Store({
   state:{
        requests:[]
   }
})

new Vue({
  el: '#app',
  router: router,
  render: h => h(App),
  store
})

利用ajax請求和終止

var xhr = $.ajax({type:'POST',
    url:'xxxsx',
    data:'',
    success:function(){
        alert('ok');
    }
})
//xhr.abort()  終止請求
this.$store.state.requests.push(xhr)

利用superagent請求 和終止

const request = require('superagent')
var xhr = request('post','/api/xxxx/xxxx')
xhr.send(data)
//xhr.query(data) //get 傳參
xhr.end((err,res)=>{
    ...todo...
})
//xhr.abort() 終止請求
this.$store.state.requests.push(xhr)

利用axios 請求

import axios from 'axios'
var CancelToken = axios.CancelToken;
var source = CancelToken.source();
axios.get('/api/xxxxx/xxxxx', {
  cancelToken: source.token
}).catch(function(thrown) {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
    // 處理錯誤
  }
});

// 取消請求(message 參數是可選的)
//source.cancel('Operation canceled by the user.');

this.$store.state.requests.push(source)

利用vue-resource請求

import Vue from 'vue'
import req from 'vue-resource'
Vue.use(req)

this.$http.get('/someUrl', {    
    before(request) {
        this.$store.state.requests.push(request)
        //request.abort(); 終止請求
    }
  }).then(response => {
    // success callback
  }, response => {
    // error callback
  });

利用fetch 請求

fetch 貌似無法監控讀取進度和終端請求,他沒有timeout機制,沒有progress提示,但是可以利用Promise 來實現終止

var _fetch = (function(fetch){
  return function(url,options){
    var abort = null;
    var abort_promise = new Promise((resolve, reject)=>{
      abort = () => {
        reject('abort.');
        console.info('abort done.');
      };
    });
    var promise = Promise.race([
      fetch(url,options),
      abort_promise
    ]);
    promise.abort = abort;
    return promise;
  };
})(fetch);

var xhr = _fetch('/api/xxx/xxxx',{methods:'POST',body:data});
xhr.then(function(res) {
    console.log('response:', res);
}, function(e) {
    console.log('error:', e);
});
xhr.abort(); //終止

this.$store.state.requests.push(xhr)

那麽知道如何終止請求,然後也存儲了請求實例,剩下的只要監聽路由就行了

let router = new Router({....})
//每次路由改變之前終止所有的請求實例
router.beforeEach(function (to, from, next) {
    this.$store.state.requests.forEach(xhr=>xhr.abort()) //終止所有的請求實例
    this.$store.state.requests =[] //執行完清空,等待下一次的頁面的請求裝載
    next()
})

這種只是假設,自然請求完成之後最好,還是手動釋放樹的請求示例。例如ajax 請求完成之後 在complite 裏面 splice store裏面的實例。

[完]

vue路由切換終止請求