ajax vuex,vue.js - AJAX wrapper for Vuex - Stack Overflow

本文介绍了一种Vue插件,用于通过队列管理用户输入实时保存到服务器,避免请求乱序。作者将该功能迁移到Vuex模块中,以便于在任何组件中统一调用并更新UI显示保存状态。讨论了如何在Vuex中实现类似功能以及如何更新UI以同步保存进度。
摘要由CSDN通过智能技术生成

The current situation

I have implemented a Vue plugin that manages the calls to the server using queues.

I have an auto-save UI that whenever user leaves an input the Client Side code sends the UiState to the server for storing in the DB. Since the user may enter and leave many inputs in short time the Ajax Requests might not received from the server in sequence.

Since I send the complete UiState object and the server might not receive the requests in the same order as send, I might not save the last change at the server but a previous.

This is why I implemented the following plugin for Vue. It uses a Queue and if by the time the server responds to the save request a new save request has been triggered, it sends only the latest save-request.

import axios from "Axios"

import qs from 'qs';

export default {

install(Vue, pluginOptions) {

var ajs = {}; //ajax-saving

var defaultPluginOptions = {

indicatorElement: null

};

// saving flags

ajs.isSaving = false;

ajs.pendingSaving = false;

ajs.pendingRequests = [];

// the indicator element

ajs.indicator = null;

ajs.indicatorTitle = null;

Vue.prototype.$ajaxSaveData = function (serverUrl, data, callback) {

//use pending flag for the function to recall itself when it finishes

if (ajs.isSaving) {

ajs.pendingSaving = true;

ajs.pendingRequests.push({ serverUrl: serverUrl, data: data, callback: callback });

console.log('%cAjaxSaving %cThe save action is queued!', 'color:#67A9BF;', 'color:#E3DC29');

return;

}

onSaveStarted();

axios({

url: serverUrl,

method: 'POST',

headers: { 'content-type': 'application/x-www-form-urlencoded' },

data: qs.stringify(data),

})

.then(result => {

onSaveEnded();

if (callback) callback(true, result);

})

.catch(function (error) {

console.log(error);

onSaveEnded(true);

if (callback) callback(false);

})

}

// saving events

var onSaveStarted = function () {

ajs.isSaving = true;

ajs.indicator.removeClass('error');

ajs.indicator.addClass('saving');

ajs.indicator.show();

ajs.indicatorTitle.html("Saving");

console.log('%cAjaxSaving %cStarted!', 'color:#67A9BF;', 'color:#7DBF67');

}

var onSaveEnded = function (error) {

ajs.isSaving = false;

ajs.indicator.removeClass('saving');

if (error) {

ajs.indicator.addClass('error');

ajs.indicatorTitle.html("Error");

console.log('%cAjaxSaving %cError!', 'color:#67A9BF;', 'color:#E60909');

} else {

ajs.indicatorTitle.html("Saved");

}

console.log('%cAjaxSaving %cEnded!', 'color:#67A9BF;', 'color:#091152');

// execute the pending savings

if (ajs.pendingSaving) {

var pendingToProcess = ajs.pendingRequests;

ajs.pendingRequests = [];

ajs.pendingSaving = false;

console.log('%cAjaxSaving %cExecuting Pending!', 'color:#67A9BF;', 'color:#E83CC5');

// process all pending request found in stack.

// skip older requests if newer are found

var req;

var processedRequests = [];

while ((req = pendingToProcess.pop()) != null) {

if (!processedRequests.includes(req.serverUrl)) {

processedRequests.push(req.serverUrl);

var executingReq = req;

setTimeout(function () {

Vue.prototype.$ajaxSaveData(executingReq.serverUrl, executingReq.data, executingReq.callback);

}, 0);

}

}

}

}

var testOptions = function () {

if (!ajs.options.indicatorElement) {

throw ('indicator element is not set');

}

}

//TODO: Remove jquery

// Plugin initialization

var createIndicator = function () {

ajs.indicator = $(ajs.options.indicatorElement);

ajs.indicatorTitle = ajs.indicator.find('span');

if (ajs.indicatorTitle.length === 0) {

ajs.indicatorTitle = $('');

ajs.indicator.append(ajs.indicatorTitle);

}

}

var initialize = function () {

//initialize options and elements needed from plugin

ajs.options = $.extend({}, defaultPluginOptions, pluginOptions);

testOptions();

createIndicator();

};

initialize();

}

}

To use this:

import Vue from "vue";

import VueAjaxSaving from '@/Plugins/VueAjaxSaving'

Vue.use(VueAjaxSaving, { indicatorElement: '#ajaxIndicator' });

new Vue({

data: {

uiState: {....}

},

methods:{

updateUiState() {

this.$ajaxSaveData('/Page/UpdateUiState', { uiState: this.uiState }, () => this.someCallback());

},

}

})

The plugin takes as parameter an element(the jQuery selector) and updates the ui with the saving state.

The need

I am refactoring my code to use Vuex for my state and I want the Vuex module to handle saving when something is mutated.

I want to provide my Vuex Modules a function that handles the save in the same way my Vue components did. With the ease of calling ajaxSaveData('url',data).then(...) from any Vuex action.

I need to update a UI part with the saving status.

The questions

What do I have to use to fill my needs?

Vuex plugin?

A class function that is imported within the Module file and used as dirty as it sounds?

A new module that contains all the saving logic ajaxSaveData? I suppose any module can dispatch it's actions.

How to update the UI for the ajaxSaveData Vuex (plugin/Class/Module)?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值