@planjs/utils
Version:
🔧 Common tools collection
104 lines (84 loc) • 2.93 kB
JavaScript
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import { prefSetTimeout, clearPrefTimeout } from '../function/pref-setTimeout';
import isObject from '../is/is-Object';
import asyncPool from '../promise/async-pool';
function asyncWorker(ctx) {
var handlers = [];
var ctrlMap = {};
function _onMessage(ev) {
var messagePort = ev.ports[0];
if (messagePort) {
handlers.forEach(function (handler) {
Promise.resolve(handler(ev)).then(function (result) {
messagePort.postMessage(result);
}, function (err) {
messagePort.postMessage(_defineProperty({}, asyncWorker.ERRKey, err));
}).catch(function (err) {
console.log('[asyncWorker] onmessage error', err);
}).finally(function () {
messagePort.close();
});
});
}
}
function postMessage(payload, opts) {
var timer = 0;
var _MessageChannel = new MessageChannel(),
port1 = _MessageChannel.port1,
port2 = _MessageChannel.port2;
var _doPost = function _doPost() {
return new Promise(function (resolve, reject) {
port1.onmessage = function (ev) {
if (isObject(ev.data) && asyncWorker.ERRKey in ev.data) {
reject(ev.data[asyncWorker.ERRKey]);
} else {
resolve(ev.data);
}
};
port1.onmessageerror = reject;
ctx.postMessage(payload, [port2].concat(_toConsumableArray((opts === null || opts === void 0 ? void 0 : opts.transfer) || [])));
if (opts !== null && opts !== void 0 && opts.timeout) {
timer = prefSetTimeout(function () {
reject(new Error('timeout'));
}, opts.timeout);
}
}).finally(function () {
port1.close();
timer && clearPrefTimeout(timer);
});
}; // 启用并发控制
if (opts !== null && opts !== void 0 && opts.concurrent) {
if (!ctrlMap[opts === null || opts === void 0 ? void 0 : opts.concurrent.key]) {
ctrlMap[opts === null || opts === void 0 ? void 0 : opts.concurrent.key] = asyncPool({
maxConcurrency: opts.concurrent.max
});
}
return ctrlMap[opts === null || opts === void 0 ? void 0 : opts.concurrent.key].executor(_doPost);
}
return _doPost();
}
/**
* 只处理使用asyncWorker postMessage 发送的事件
* @param fn 返回值作为 postMessage 的返回结果
*/
function register(fn) {
handlers.push(fn);
}
function _listen() {
ctx.addEventListener('message', _onMessage);
}
function setCtx(c) {
ctx.removeEventListener('message', _onMessage);
ctx = c;
_listen();
}
_listen();
return {
setCtx: setCtx,
postMessage: postMessage,
register: register
};
}
asyncWorker.ERRKey = '__err__';
export default asyncWorker;