UNPKG

@gdjiami/jslib

Version:

Jiami FrontEnd helpers and Services

224 lines (223 loc) 7.68 kB
/** * promise、异步操作相关的工具函数。 */ import * as tslib_1 from "tslib"; /** * 延迟指定毫秒 */ export function delay(ms) { return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { return [2 /*return*/, new Promise(function (res) { return setTimeout(res, ms); })]; }); }); } /** * 增加超时机制的promise */ export function promiseWithTimeout(prom, timeout) { return tslib_1.__awaiter(this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { return [2 /*return*/, new Promise(function (resolve, reject) { var resolved; var resolver = function (val) { if (resolved) { return; } resolved = true; resolve(val); }; var rejector = function (reason) { if (resolved) { return; } resolved = true; reject(reason); }; setTimeout(function () { return rejector(new Error('timeout')); }, timeout); prom(resolver, rejector); })]; }); }); } /** * 可重试的promise, 出现异常时进行重试 * @param prom * @param time 重试的次数 * @param duration 重试的间隔 */ export function retryablePromise(prom, time, duration) { if (time === void 0) { time = 1; } if (duration === void 0) { duration = 0; } return tslib_1.__awaiter(this, void 0, void 0, function () { var i, rt, err_1; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: i = 0; _a.label = 1; case 1: if (!(i < time)) return [3 /*break*/, 8]; _a.label = 2; case 2: _a.trys.push([2, 4, , 7]); return [4 /*yield*/, prom()]; case 3: rt = _a.sent(); return [2 /*return*/, rt]; case 4: err_1 = _a.sent(); if (!(i < time)) return [3 /*break*/, 6]; return [4 /*yield*/, delay(duration)]; case 5: _a.sent(); return [3 /*break*/, 7]; case 6: throw err_1; case 7: i++; return [3 /*break*/, 1]; case 8: return [2 /*return*/, undefined]; } }); }); } /** * 抽取出promise的Resolve和Reject函数, 可以在外部进行使用 * * @example * ```js * const { promise, reject, resolve } = extraPromise() * ``` */ export function extraPromise() { return tslib_1.__awaiter(this, void 0, void 0, function () { var resolve, reject, promise; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: promise = new Promise(function (res, rej) { resolve = res; reject = rej; }); return [4 /*yield*/, delay(0)]; case 1: _a.sent(); return [2 /*return*/, { promise: promise, reject: reject, resolve: resolve, }]; } }); }); } /** * 按照 push 顺序执行并发的任务 * 防止并发多个任务只执行一个任务后其他任务被销毁 * * @typeParam R 自定义返回值类型 * * @returns push 将异步操作加入任务队列,run 按顺序执行任务队列里的所有异步操作 * * @example * * ```js * * const tasks = concurrentTask<MessageData[] | undefined>() * * for (let i = 0; i < messages.length; i++) { * tasks.push(() => {}) // tasks.push(Promise<any>) * } * const res = await tasks.run() * * ``` */ export function concurrentTask() { var _this = this; var i = 0; var tasks = []; var run = function () { return tslib_1.__awaiter(_this, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { return [2 /*return*/, Promise.all(tasks).then(function (arr) { return arr.sort(function (a, b) { return a.index - b.index; }).map(function (i) { return i.res; }); })]; }); }); }; var push = function (task) { var order = i++; tasks.push(new Promise(function (resolve, reject) { task() .then(function (res) { resolve({ index: order, res: res }); }) .catch(reject); })); }; return { push: push, run: run, }; } var pendingTask = {}; /** * 执行异步任务, 它会处理重复发起的任务 * @param id 任务唯一索引 * @param task 异步执行方法 * * @example * * ```js * const res = await executeAsyncTask<User>('get-user', async () => Promise<User>) // 如多次发起请求,只会请求一次 * ``` */ export function executeAsyncTask(id, task) { return tslib_1.__awaiter(this, void 0, void 0, function () { var e_1, _a, res, err, err_2, _b, _c, t; return tslib_1.__generator(this, function (_d) { switch (_d.label) { case 0: if (id in pendingTask) { return [2 /*return*/, new Promise(function (resolve, reject) { pendingTask[id].push({ resolve: resolve, reject: reject }); })]; } _d.label = 1; case 1: _d.trys.push([1, 3, , 4]); pendingTask[id] = []; return [4 /*yield*/, task()]; case 2: res = _d.sent(); return [3 /*break*/, 4]; case 3: err_2 = _d.sent(); err_2 = err_2; return [3 /*break*/, 4]; case 4: try { for (_b = tslib_1.__values(pendingTask[id]), _c = _b.next(); !_c.done; _c = _b.next()) { t = _c.value; if (err != null) { t.reject(err); } else { t.resolve(res); } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) _a.call(_b); } finally { if (e_1) throw e_1.error; } } delete pendingTask[id]; if (err != null) { throw err; } return [2 /*return*/, res]; } }); }); }