Worker线程中获取异步类方法返回结果的问题求助
问题描述
在Worker线程中调用包含await操作的类方法时,始终得到Promise pending状态的结果。尝试在Worker线程中使用await会抛出“Promise无法克隆”的异常。需要在worker.js中获取getTicketBindings方法的最终返回结果,相关代码如下:
worker.js 原代码
const { parentPort, workerData } = require("worker_threads"); const ObjectParameters = require('./ObjectAttributes.js'); const execute = (workerData) => { return test(workerData.element, workerData.userDto); }; parentPort.postMessage(execute(workerData)); // event handler function test(element, userDto) { // dont put aysn in worker thread otherwise promise cannot be cloned exception var AttributeArray = new ObjectParameters.Attributes(userDto); var ticketBinding = AttributeArray.getTicketBindings(element); // need this awaited result sleep(2000); if (ticketBinding !== null || ticketBinding !== undefined) { return ticketBinding; } var output = JSON.stringify(ticketBinding); if (output !== null | undefined) { return output; } } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
ObjectAttributes.js 类代码
var JiraApi = require('jira-client'); const utils = require('./Utils.js') const Global = require('./Global.js') class Attributes { _reponse; _params = {}; _response = null; jira = null; constructor(userDto) { this.jira = new JiraApi({ protocol: userDto.protocol, host: userDto.host, username: userDto.username, password: userDto.password, apiVersion: userDto.apiVersion, strictSSL: userDto.strictSSL }); } async getAttributes(element) { this._response = await this.getIssue(element); this._params['sprintId'] = await this.getSprintId(this._response); this._params['Comments'] = await this.getComments(this._response); return this._params; } async getIssue(element) { var response = await this.jira.getIssue(element.id).then(function (response) { return response; }).catch(error => { console.log(error); return "undefined"; }) return response; } async getSprintId(response) { try { var sprint = response.fields.sprint; if ((sprint !== null) && (sprint !== undefined)) { var id = sprint.id; if ((id !== null) && (id !== undefined)) { return id; } } return "00000000-0000-0000-0000-000000000000"; } catch (error) { // if incase connection breaks return "00000000-0000-0000-0000-000000000000"; } } async getComments(response) { try { var commentArray = []; var comments = response.fields.comment.comments; if ((comments !== null) && (comments !== undefined)) { if (comments.length !== 0) { comments.forEach(element => { commentArray.push(element.body); }); } return commentArray; } return []; } catch (error) { return []; } } getSprintName(response) { try { var sprint = response.fields.sprint; if ((sprint !== null) && (sprint !== undefined)) { var name = sprint.name; if ((name !== null) && (name !== undefined)) { return name; } } return ""; } catch (error) { // if incase connection breaks return " "; } } async getTicketBindings(element) { if (element.fields.issuetype.name == 'Bug') { var jiraResponse = await this.getAttributes(element); var ticketBinding = { ArtifactType: 'Ticket', ArtifactMode: "", ArtifactSteps: "", TicketNumber: null, ElementId: element.key, Summary: element.fields.summary, Description: utils.getFormatedDescription(element.fields.description), Assignee: "", Reporter: "", Priority_Enum: element.fields.priority.name, TicketType: "", State_Enum: element.fields.status.name, SprintID: jiraResponse.sprintId || "00000000-0000-0000-0000-000000000000",//await getSprintName(element.key, jira), Resolution: element.fields.resolution, Tags: utils.getLabels(element.fields.labels, element.key), Comments: jiraResponse.Comments || [] //await getComments(element.key, jira) }; return ticketBinding; } } } module.exports = { Attributes: Attributes }
解决方案
问题根源:getTicketBindings是异步方法,直接调用返回Promise,而Worker的postMessage无法克隆Promise对象;同时原代码没有等待异步操作完成就返回结果,导致拿到pending状态的Promise。
修改后的worker.js代码:
const { parentPort, workerData } = require("worker_threads"); const ObjectParameters = require('./ObjectAttributes.js'); // 异步执行逻辑,等待结果后再发送消息 const execute = async (workerData) => { const result = await test(workerData.element, workerData.userDto); parentPort.postMessage(result); }; execute(workerData); // 改成异步函数,等待getTicketBindings完成 async function test(element, userDto) { const attributeArray = new ObjectParameters.Attributes(userDto); // 等待异步方法返回最终结果 const ticketBinding = await attributeArray.getTicketBindings(element); if (ticketBinding) { // 转成纯JSON对象,避免Jira返回的特殊对象无法克隆 return JSON.parse(JSON.stringify(ticketBinding)); } return null; }
关键修改点:
- 将
test改为异步函数,用await等待getTicketBindings的结果,拿到最终的对象而非Promise execute函数改为异步,等待test执行完成后再调用postMessage发送结果- 移除原代码中无效的
sleep调用(它是异步的,不会阻塞代码,反而会提前返回Promise) - 用
JSON.parse(JSON.stringify(ticketBinding))确保返回的是可序列化的纯对象,避免Worker消息通道无法克隆特殊对象的问题
内容的提问来源于stack exchange,提问作者arjun singh
相关产品推荐
相关产品推荐

