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

如何在同步函数返回的对象中解析Promise为实际值?

在非async函数中替换对象内所有Promise为解析后的值

我需要在一个受API约束无法声明为async的同步函数中返回一个数据对象,但部分数据为Promise类型。我可以通过Promise.all([<promises>]).then(callback)延迟回调至Promise解析完成,但返回的对象仍包含大量Promise。如何无需逐个处理所有项就将对象中所有Promise替换为其解析后的值?

背景

本次场景为开发Chrome扩展。Chrome扩展分为两部分:作为核心脚本的后台「service worker」,以及作用于每个页面的「content scripts」。部分操作只能在后台脚本中完成,比如获取当前窗口的标签页,这需要通过消息API从content scripts调用后台函数。

细节

当前API实现如下:

chrome.runtime.onMessage.addListener(messageHandler)

// Example "message" object: { get: { globalFunctions: ['getCurrentTab'] } }
function messageHandler(message, sender, callback) {
    const responseObject = {}
    const promises = []
    if (message.get) {
        const get = message.get
        const res = {}
        if (get.globalFunctions) {
            const funcNames = conformToStringArr(get.globalFunctions)
            if (!funcNames)
                return;
            
            res.globalFunctions = {}
            funcNames.forEach((funcName) => {
                res.globalFunctions[funcName] = globalFunctions[funcName](message, sender) // Functions can be async because they have to asynchronously retrieve values
            })
        }
        if (get.globalValues) {
            const globalNames = conformToStringArr(get.globalValues)
            if (!globalNames)
                return;
            
            res.globalValues = {}
            globalNames.forEach((valueName) => {
                res.globalValues[valueName] = globalValues[valueName]
            })
        }
        if (get.localStorage) {
            const toGet = conformToStringArr(get.localStorage)
            if (!toGet)
                return;
            
            res.localStorage = chrome.storage.local.get(toGet) // : Promise
        }
        
        responseObject.get = res
    }
    callback(responseObject)
    
    return true; // Required due to restrictions of the message API. I cannot return a Promise or use an asynchronous function.
}

本质上我是按同步逻辑填充对象并返回,但问题在于部分值是Promise,而Promise引用不会自动解析为对应值。我已掌握Promise的控制流逻辑,但这种值替换的方法在网上鲜有提及。

我可以将所有Promise加入数组,通过Promise.all(promises).then(callback)在所有Promise完成后再返回对象,但这样返回的对象仍会充满Promise,对吗?

如何从这类非async函数中返回不含Promise的对象?

解决方案

改为将赋值操作包裹在Promise中。例如,不要使用outObject.bar = asyncFoo()(asyncFoo返回Promise),而是使用asyncFoo().then((value) => outObject.bar = value)。为确保所有值填充完成后再返回对象,将每个Promise加入「promises」数组,并在函数末尾添加Promise.allSettled(promises).then(() => callback(outObject))。

最终代码:

function messageHandler(message, sender, callback) {
    const responseObject = {}
    const promises = []
    if (message.get) {
        const get = message.get
        responseObject.get = {}
        if (get.globalFunctions) {
            const funcNames = conformToStringArr(get.globalFunctions) 
            if (funcNames) {
                responseObject.get.globalFunctions = {}
                funcNames.forEach((name) => {
                    const functionResult = globalFunctions[name](message, sender)
                    if (functionResult instanceof Promise)
                        promises.push(functionResult.then((value) => responseObject.get.globalFunctions[name] = value))
                    else
                        responseObject.get.globalFunctions[name] = functionResult
                })
            }
        }
        if (get.globalValues) {
            const globalNames = conformToStringArr(get.globalValues)
            if (globalNames) {
                responseObject.get.globalValues = {}
                globalNames.forEach((valueName) => {
                    responseObject.get.globalValues[valueName] = globalValues[valueName]
                })
            }
        }
        if (get.localStorage) {
            const toGet = conformToStringArr(get.localStorage)
            if (toGet)
                promises.push(chrome.storage.local.get(toGet).then((value) => responseObject.get.localStorage = value))
        }
        
    }
    if (promises.length > 0) {
        Promise.allSettled(promises).then(() => callback(responseObject))
    } else {
        callback(responseObject)
    }
    
    return true;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 13:50:39