-
一般使用worker都是單獨執行一個js腳本文件;最近發現一個vue插件,vue-worker,支持了傳入一個方法,就可以讓這個方法在worker線程執行;使用worker更加方便;
vue-worker地址:https://www.npmjs.com/package/vue-worker
安裝:
npm install vue-worker --save
vue2使用:
import Vue from 'vue' import VueWorker from 'vue-worker' Vue.use(VueWorker)
可以用this.$worker調用
vue3使用:
import vueWorker from 'simple-web-worker'
主要用到run和create方法:
run:
this.$worker.run(func, [args]?)
func是在worker中運行的函數;
[args]是函數需要的參數,用數組盛放;
例子:
this.$worker.run((a, b) => { return a+b; }, [1,2]) .then(res => { console.log(res) // 3 }) .catch(err => { console.log(err) })
this.$worker.create([actions]?)
如果打算重用worker,需要用create
它生成一個實例,
通過它的postMessage()或postAll()方法運行確定的操作。
例:
const actions = [ { message: 'func1', func: () => `Worker 1: Working on func1` }, { message: 'func2', func: arg => `Worker 2: ${arg}` }, { message: 'func3', func: arg => `Worker 3: ${arg}` }, { message: 'func4', func: (arg = 'Working on func4') => `Worker 4: ${arg}` } ] let worker = this.$worker.create(actions)
發現這個插件不能夠傳入promise,有時候就有些不夠好用;根據源碼,稍微改了個簡單的可以傳入promise的插件:
promiseWorker.js
const argumentError = function (r) { var e = r.expected, n = void 0 === e ? "" : e, t = r.received, o = r.extraInfo, i = void 0 === o ? "" : o; try { return new TypeError("You should provide " + n + "\n" + i + "\nReceived: " + JSON.stringify(t)) } catch (r) { if ("Converting circular structure to JSON" === r.message) return new TypeError("You should provide " + n + "\n" + i + "\nReceived a circular structure: " + t); throw r } } const getType = (param) => { return Object.prototype.toString.call(param).replace(/[\[|\]]/g, '').split(/\s/)[1]; } const makeResponse = function (r) { return "\n self.onmessage = async (event) => {\n const args = event.data.message.args\n if (args) {\n const result = await (" + r + ").apply(null, args)\n self.postMessage(result)\n return close()\n }\n \n const result = await (" + r + ").apply(null, args)\n self.postMessage(result)\n return close()\n }\n" }; const createDisposableWorker = function (r) { var e = window.URL || window.webkitURL, n = new Blob([r], { type: "application/javascript" }), t = e.createObjectURL(n), o = new Worker(t); return o.post = function (r) { return new Promise(function (n, i) { o.onmessage = function (r) { e.revokeObjectURL(t), n(r.data) }; o.onerror = function (r) { console.error("Error: Line " + r.lineno + " in " + r.filename + ": " + r.message), i(r) }; o.postMessage({ message: r }); }) }, o } const run = function () { let r = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : null, e = arguments[1], n = getType(r) === 'Function', t = getType(e) === 'Array'; if (n && t) { return createDisposableWorker(makeResponse(r)).post({ args: e }) } return n || console.error(argumentError({ expected: "a function", received: r })), t || console.error(argumentError({ expected: "an array", received: e })), null } export default run
使用:
const fn = (a) => { return new Promise(resolve => { setTimeout(() => { resolve(a) }, 1000) }) }; run(fn, [1]).then(res => { console.log(res, 'res'); // 1 })
-