axios-series
Version:
A tool to extend axios to return sequentially
230 lines (224 loc) • 7.8 kB
JavaScript
;
var tslib = require('tslib');
var axios = require('axios');
var Serializer = /** @class */function () {
function Serializer(instance, options) {
this.waiting = {};
this.unique = false;
this.orderly = true;
this.onCancel = null;
var defaultOptions = {
unique: false,
orderly: true
};
options = Object.assign(defaultOptions, options || {});
this.axiosInstance = instance;
this.unique = options.unique;
this.orderly = options.orderly;
options.onCancel && (this.onCancel = options.onCancel);
}
/**
* Do request
*
* @param config - axios request config
* @returns - Promise<unknown>
*/
// public async request<T = any, R = AxiosResponse<T>, D = any>(
// config: SerializerRequestOptions<D>
// ): Promise<R>
// public async request<T = any, R = AxiosResponse<T>, D = any>(
// url: string,
// config?: SerializerRequestOptions<D>
// ): Promise<R>
Serializer.prototype.request = function (
// url: string | SerializerRequestOptions<D>,
config) {
return tslib.__awaiter(this, void 0, void 0, function () {
var _a, unique, _b, orderly, _c, url, promiseKey, source, abortController, promise;
var _this = this;
return tslib.__generator(this, function (_d) {
_a = config.unique, unique = _a === void 0 ? this.unique : _a, _b = config.orderly, orderly = _b === void 0 ? this.orderly : _b, _c = config.url, url = _c === void 0 ? '' : _c;
promiseKey = Symbol('promiseKey');
source = axios.CancelToken.source();
// config.requestOptions = extend(true, {}, options)
config.cancelToken = source.token;
if (typeof AbortController === 'function') {
abortController = new AbortController();
config.signal = abortController.signal;
}
unique && this.clear(url);
promise = new Promise(function (resolve, reject) {
_this.axiosInstance(config).then(function (res) {
if (!orderly) resolve(res);else _this.wait(url, promiseKey).then(function () {
resolve(res);
});
}).catch(function (err) {
// Request cancelled
if (axios.isCancel(err)) _this.onCancel && _this.onCancel(err, config);
// Request error
else reject(err);
}).finally(function () {
var index = _this.waiting[url].findIndex(function (el) {
return el.promiseKey === promiseKey;
});
index > -1 && _this.waiting[url].splice(index, 1);
});
});
this.add(url, {
promiseKey: promiseKey,
promise: promise,
source: source,
abortController: abortController
});
return [2 /*return*/, promise];
});
});
};
/**
* Drop all un-need requests
*
* @param key - the key of waiting line, usually to be the request url
*/
Serializer.prototype.clear = function (key) {
var e_1, _a;
for (var url in this.waiting) {
// no key => clean all
if (!key || url === key) {
var seriesList = this.waiting[url] || [];
try {
for (var seriesList_1 = (e_1 = void 0, tslib.__values(seriesList)), seriesList_1_1 = seriesList_1.next(); !seriesList_1_1.done; seriesList_1_1 = seriesList_1.next()) {
var series = seriesList_1_1.value;
series.source.cancel('request canceled');
series.abortController && series.abortController.abort();
}
} catch (e_1_1) {
e_1 = {
error: e_1_1
};
} finally {
try {
if (seriesList_1_1 && !seriesList_1_1.done && (_a = seriesList_1.return)) _a.call(seriesList_1);
} finally {
if (e_1) throw e_1.error;
}
}
this.waiting[url] = [];
}
}
};
/**
* Waiting to resolve the series before this request
*
* @param key - the key of waiting line, usually to be the request url
* @param promiseKey - the unique promise key
* @returns - Promise<void>
*/
Serializer.prototype.wait = function (key, promiseKey) {
return tslib.__awaiter(this, void 0, void 0, function () {
var seriesList, index;
return tslib.__generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!this.orderly) return [2 /*return*/, Promise.resolve()];
seriesList = this.waiting[key] || [];
index = seriesList.findIndex(function (item) {
return item.promiseKey === promiseKey;
});
_b.label = 1;
case 1:
if (!(index > 0)) return [3 /*break*/, 7];
index--;
if (!(seriesList[index] && seriesList[index].promiseKey !== promiseKey)) return [3 /*break*/, 6];
_b.label = 2;
case 2:
_b.trys.push([2, 4,, 5]);
return [4 /*yield*/, seriesList[index].promise
// await seriesList.splice(index, 1)[0].promise
];
case 3:
_b.sent();
return [3 /*break*/, 5];
case 4:
_b.sent();
console.info('The task has been dropped');
return [3 /*break*/, 5];
case 5:
seriesList.splice(index, 1);
_b.label = 6;
case 6:
return [3 /*break*/, 1];
case 7:
return [2 /*return*/];
}
});
});
};
/**
* set series to waiting list
*
* @param key - the key of waiting line, usually to be the request url
* @param series - waiting object
*/
Serializer.prototype.add = function (key, series) {
if (!(key in this.waiting)) this.waiting[key] = [];
this.waiting[key].push(series);
};
return Serializer;
}();
/**
* axios serializer wrapper function
*
* @param instance - axios or axios instance
* @param options - serializer options
* @return - axios instance with serializer feature
*/
function axiosSeries(instance, options) {
var serializer = new Serializer(instance, options);
function axiosWithSeries(url, config) {
var _a;
if (typeof url !== 'string') {
config = url;
} else {
config !== null && config !== void 0 ? config : config = {};
(_a = config.url) !== null && _a !== void 0 ? _a : config.url = url;
}
return serializer.request(config);
}
// axiosWithSeries.defaults = instance.defaults
// axiosWithSeries.interceptors = instance.interceptors
// axiosWithSeries.getUri = instance.getUri
// axiosWithSeries.request = instance.request
// axiosWithSeries.get = instance.get
// axiosWithSeries.delete = instance.delete
// axiosWithSeries.head = instance.head
// axiosWithSeries.options = instance.options
// axiosWithSeries.post = instance.post
// axiosWithSeries.put = instance.put
// axiosWithSeries.patch = instance.patch
// axiosWithSeries.postForm = instance.postForm
// axiosWithSeries.putForm = instance.putForm
// axiosWithSeries.patchForm = instance.patchForm
// axiosWithSeries.create = instance.create
// not in axios instance
// axiosWithSeries.Cancel = instance.Cancel
// axiosWithSeries.CancelToken = instance.CancelToken
// axiosWithSeries.Axios = instance.Axios
// axiosWithSeries.VERSION = instance.VERSION
// axiosWithSeries.isCancel = instance.isCancel
// axiosWithSeries.all = instance.all
// axiosWithSeries.spread = instance.spread
// axiosWithSeries.isAxiosError = instance.isAxiosError
/**
* all waiting series
*/
axiosWithSeries.series = serializer.waiting;
/**
* clear all series
*/
axiosWithSeries.clear = function () {
// clear all
serializer.clear();
};
return axiosWithSeries;
}
module.exports = axiosSeries;