公司项目中遇到了要求使用webWorker进行数据下载的操作
让把之前在主线程发送axios请求的操作下放到webWorker中
项目是在Capacitor框架中的,原先封装的request的请求方法调用了
Capacitor的初始化App方法,这个初始化方法操作了dom,所以不能在子线程中调用
原来的思路是在线程中实例化一个Axios的实例来进行请求的操作,因为请求涉及到了添加数据和请求头的操作
而这些数据都保持在主线程的框架插件PreferencesPlugin中,子线程拿不到只能通过postMessage传
但是经过组长的沟通后,每次发送都直接使用axios.post() 而不是使用Axios的构造器
理由是只是简单的post请求,没必要使用构造器。但是还是需要去处理报错事件的,比如404,500等
原来的想法是在index.ts调用utils.ts工具类函数,utils调用webWorker脚本文件。
在utils中监听onerroer事件捕获报错
在webWorker中使用throw抛出错误
原来是这么写的
webWorker.ts
self.onmessage = function(e:MessageEvent<{
config:{
url:string,
data:UpdateTableTask[],
config:AxiosRequestConfig
}
}>) {
request(e.data.config)
}
/**
* 发起请求
*
* @param config 请求参数
*/
async function request(requestParams: {
url:string,
data:UpdateTableTask[],
config:AxiosRequestConfig
}) {
try {
const respone = await axios.post<ResponseEntity<EncryptedResponse>>(requestParams.url, requestParams.data, requestParams.config)
self.postMessage({
type: 'success',
data: respone.data.data
})
} catch (error) {
throw new Error(error)
}
}
utils.ts
export function webWorkerRequest(config:{
url:string,
data:UpdateTableTask[],
config:AxiosRequestConfig
}): Promise<ResponseEntity<EncryptedResponse>> {
if (Worker) {
worker = new Request()
return new Promise((resolve, reject) => {
worker.onmessage = (event) => {
if (event.data.type === 'error') {
reject(event.data.message)
} else {
resolve(event.data)
}
worker.terminate()
}
worker.postMessage({
config
})
Worker.onerrron = (error) => {
reject(error)
}
})
} else {
throw new Error('Web Worker不可用')
}
}
在子线程的catch中可以正常的捕获到异常打印
但是就是没办法在utils中的onerror事件中捕获
后来经过几次测试,发现在异步函数中的报错不会被主线程的onerror监听事件捕获
不管是使用async await 还是Promise只要是异步的主线程都接收不到
随后改成使用postMessage的模式,通过一个type区分成功还是失败去传递
webWorker.ts
async function request(requestParams: {
url:string,
data:UpdateTableTask[],
config:AxiosRequestConfig
}) {
try {
const respone = await axios.post<ResponseEntity<EncryptedResponse>>(requestParams.url, requestParams.data, requestParams.config)
self.postMessage({
type: 'success',
data: respone.data.data
})
} catch (error) {
console.error(error)
self.postMessage({
type: 'error',
message: (error as AxiosError).message ?? '请求失败'
})
}
}
这样主线程就可以正常的接收到子线程的报错消息。