You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;
}

关键修改点:

  1. 将test改为异步函数,用await等待getTicketBindings的结果,拿到最终的对象而非Promise
  2. execute函数改为异步,等待test执行完成后再调用postMessage发送结果
  3. 移除原代码中无效的sleep调用(它是异步的,不会阻塞代码,反而会提前返回Promise)
  4. 用JSON.parse(JSON.stringify(ticketBinding))确保返回的是可序列化的纯对象,避免Worker消息通道无法克隆特殊对象的问题

内容的提问来源于stack exchange,提问作者arjun singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 12:35:56