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

如何在PowerShell中执行异步Node.js代码并获取返回结果?

解决PowerShell调用Node.js异步脚本无法获取结果的问题

问题背景

在PowerShell中调用Node.js脚本执行异步HubSpot API请求时,PowerShell会在Node脚本的异步操作完成前继续执行,无法捕获异步返回的联系人数据。尝试使用Start-Job也未能解决问题。

现有代码

PowerShell脚本

$hubspot_api_key = 'xxx'

$result = $(node hubspot.js $($hubspot_api_key) 'ci')

Write-Output 'Results:' $result

Node.js核心代码

(async () => { return await getContacts(); })()

Node.js补充代码(getContacts函数)

getContacts = async () => {
    const emailFilter = `*bstdev${environment}*`
    console.log('emailFilter', emailFilter);
    const filter = { propertyName: 'email', operator: 'EQ', value: emailFilter }
    const filterGroup = { filters: [filter] }
    const sort = JSON.stringify({ propertyName: 'createdate', direction: 'DESCENDING' })
    const query = 'test'
    const properties = ['createdate', 'firstname', 'lastname']
    const limit = 100
    const after = 0

    const contacts = [];

    const publicObjectSearchRequest = {
        filterGroups: [filterGroup],
        sorts: [sort],
        query,
        properties,
        limit,
        after,
    }

    let result = await hubspotClient.crm.contacts.searchApi.doSearch(publicObjectSearchRequest);

    if(result.results){
        result.results.forEach((publicObject) => {
            contacts.push(publicObject.properties);            
        })

        while(result.paging){
            publicObjectSearchRequest.after = result.paging.next.after;

            await setAsyncTimeout(async() => {
                result = await hubspotClient.crm.contacts.searchApi.doSearch(publicObjectSearchRequest);
                if(result.results){
                    result.results.forEach((publicObject) => {
                        contacts.push(publicObject.properties);                
                    })
                }
            }, 1000);
        }
    }    

    console.log('count', contacts.length);
    
    return contacts;
}

问题根源

  1. Node.js中的异步立即执行函数(IIFE)仅启动了异步操作,但未等待其完成就退出进程,导致PowerShell无法捕获最终结果。
  2. Async函数的返回值不会自动输出到标准输出(stdout),PowerShell只能通过捕获stdout内容获取结果。
  3. 错误使用Start-Job:$someFunc已经是node命令的执行结果,而非可执行的脚本块,因此无法通过Job机制等待结果。

解决方案

1. 修改Node.js脚本,确保异步操作完成后输出结果

  • 等待异步函数执行完成,将结果以JSON格式输出到stdout(方便PowerShell解析)。
  • 补全缺失的依赖代码(如setAsyncTimeout定义、hubspotClient初始化、环境变量获取)。
  • 处理错误,避免进程意外退出。

修改后的hubspot.js代码:

// 补全setAsyncTimeout函数定义
function setAsyncTimeout(callback, delay) {
    return new Promise(resolve => {
        setTimeout(async () => {
            await callback();
            resolve();
        }, delay);
    });
}

// 从命令行参数获取API密钥和环境
const hubspotApiKey = process.argv[2];
const environment = process.argv[3];

// 初始化HubSpot客户端(需确保已安装@hubspot/api-client包)
const { Client } = require('@hubspot/api-client');
const hubspotClient = new Client({ accessToken: hubspotApiKey });

async function getContacts() {
    const emailFilter = `*bstdev${environment}*`;
    console.log('emailFilter', emailFilter);
    const filter = { propertyName: 'email', operator: 'EQ', value: emailFilter };
    const filterGroup = { filters: [filter] };
    const sort = { propertyName: 'createdate', direction: 'DESCENDING' }; // 无需JSON.stringify,直接传对象
    const query = 'test';
    const properties = ['createdate', 'firstname', 'lastname'];
    const limit = 100;
    const after = 0;

    const contacts = [];

    const publicObjectSearchRequest = {
        filterGroups: [filterGroup],
        sorts: [sort],
        query,
        properties,
        limit,
        after,
    };

    try {
        let result = await hubspotClient.crm.contacts.searchApi.doSearch(publicObjectSearchRequest);

        if (result.results) {
            result.results.forEach((publicObject) => {
                contacts.push(publicObject.properties);
            });

            while (result.paging) {
                publicObjectSearchRequest.after = result.paging.next.after;

                await setAsyncTimeout(async () => {
                    result = await hubspotClient.crm.contacts.searchApi.doSearch(publicObjectSearchRequest);
                    if (result.results) {
                        result.results.forEach((publicObject) => {
                            contacts.push(publicObject.properties);
                        });
                    }
                }, 1000);
            }
        }

        console.log('count', contacts.length);
        // 将结果以JSON格式输出到stdout,供PowerShell捕获
        console.log(JSON.stringify(contacts));
    } catch (error) {
        // 输出错误信息到stderr,避免干扰结果捕获
        console.error('Error fetching contacts:', error);
        process.exit(1);
    }
}

// 等待异步函数执行完成
getContacts();

2. 修改PowerShell脚本,直接同步调用并解析结果

无需使用Start-Job,只要Node脚本等待异步操作完成后输出结果,PowerShell会自动等待node命令执行完毕再继续。可以将捕获的JSON字符串转换为PowerShell对象,方便后续处理。

修改后的PowerShell脚本:

$hubspot_api_key = 'xxx'

# 调用Node脚本,捕获stdout输出
$rawResult = $(node hubspot.js $hubspot_api_key 'ci')

# 提取JSON结果(过滤掉日志信息,只取最后一行的JSON)
$jsonResult = $rawResult | Where-Object { $_ -match '^\[.*\]$' } | Select-Object -Last 1

# 转换为PowerShell对象
$result = if ($jsonResult) { ConvertFrom-Json $jsonResult } else { @() }

Write-Output 'Results:' $result

关键说明

  • Node脚本中必须用console.log(JSON.stringify(contacts))将结果输出到stdout,PowerShell才能捕获到结构化数据。
  • 过滤日志信息(如emailFilter、count)是为了避免干扰JSON解析,确保只处理结果数据。
  • 若Node脚本执行出错,错误信息会输出到stderr,PowerShell不会捕获到,可通过$LASTEXITCODE检查Node进程的退出码判断是否执行成功。

内容的提问来源于stack exchange,提问作者Brian Rice

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 08:10:41