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

如何用异步值填充对象?解决Promise未自动解析问题

问题描述

我有一个包含多个属性的对象,其中部分属性的值为Promise。我希望等待所有Promise完成解析后,让这些属性直接存储Promise的解析值。

目前我编写了如下代码,但对象o的o3、o4、o5属性仍然保留着已完成的Promise,而非解析后的实际值:

var f_o_data = function(b_reject){

    return new Promise(
        function(
            f_resolve, 
            f_reject
        ){

            window.setTimeout(function(){

                var n_ts_ms = parseInt(new Date().getTime());
                // if(n_ts_ms % 2 == 0){
                //     f_reject(`i rejected because n_ts_ms ${n_ts_ms} % 2 == 0 is true :shrug:`)
                // }
                if(b_reject){
                    f_reject('i rejected because true was passed to function')
                }
                f_resolve(
                    {
                        n_ts_ms: n_ts_ms,
                        s: 'i am the result object', 
                        n: 23, 
                        b: true, 
                        a_n: [1,2,3], 
                        a_o:[{n:2, n:3}, {n:3}]
                    }
                )

            },parseInt(Math.random()*3333+555))
        }
    )
}
var f_o__filled_asyncally = async function(){

    var o = {
        b: true, 
        n: 2, 
        s: 'just a string', 
        o: {n:22}, 
        a_n: [1,2,3],
        a_o:[{n:2, n:3}, {n:3}],
        o1: await f_o_data(),// 这两个异步函数会按顺序执行,因为用了await
        o2: await f_o_data(),// 
        o3: f_o_data(),// 这三个可以并行加载
        o4: f_o_data().then(function(o){return o}),// 这三个可以并行加载
        o5: f_o_data(),// 这三个可以并行加载
        // o6: f_o_data(true),// 这三个可以并行加载
    }
    return Promise.all(Object.values(o)).then(
        function(a_o_promise){
            return o
        }
    )
    // console.log(o)
    // console.log(o.o3)
    // console.log(o.o4)
    // console.log(o.o5)
    // return o;
}

var o_my_object_i_want_to_fill_asyncally = await f_o__filled_asyncally();
console.log(o_my_object_i_want_to_fill_asyncally)
解决方案

当前代码里,Promise.all(Object.values(o))只是等待所有Promise完成,但没有把解析后的结果赋值回原对象的对应属性。要实现需求,需要保留对象键和值的关联关系,等所有Promise解析完成后将结果映射回对象:

var f_o_data = function(b_reject){
    return new Promise(function(f_resolve, f_reject){
        window.setTimeout(function(){
            var n_ts_ms = parseInt(new Date().getTime());
            if(b_reject){
                f_reject('i rejected because true was passed to function')
            }
            f_resolve({
                n_ts_ms: n_ts_ms,
                s: 'i am the result object', 
                n: 23, 
                b: true, 
                a_n: [1,2,3], 
                a_o:[{n:3}, {n:3}] // 原代码中重复键会被覆盖,此处修正
            })
        }, parseInt(Math.random()*3333+555))
    })
}

var f_o__filled_asyncally = async function(){
    // 先创建对象,让o3、o4、o5立即启动并行请求
    var o = {
        b: true, 
        n: 2, 
        s: 'just a string', 
        o: {n:22}, 
        a_n: [1,2,3],
        a_o:[{n:2, n:3}, {n:3}],
        o1: await f_o_data(), // 顺序执行
        o2: await f_o_data(), // 顺序执行
        o3: f_o_data(), // 并行执行
        o4: f_o_data(), // 并行执行(原代码的then(o=>o)无意义,直接移除)
        o5: f_o_data()  // 并行执行
    }

    // 将对象转为[key, value]格式的数组,保留键值对应关系
    const entries = Object.entries(o);
    // 等待所有值(包括普通值和Promise)解析完成
    const resolvedValues = await Promise.all(entries.map(([key, value]) => value));
    // 把解析后的结果赋值回原对象的对应属性
    entries.forEach(([key], index) => {
        o[key] = resolvedValues[index];
    });

    return o;
}

var o_my_object_i_want_to_fill_asyncally = await f_o__filled_asyncally();
console.log(o_my_object_i_want_to_fill_asyncally)

关键说明

  • Object.entries(o)把对象转换成键值对数组,确保后续能准确对应每个属性的解析结果
  • Promise.all会自动处理普通值(直接返回)和Promise(等待解析),无需额外判断
  • 遍历键值对数组,将解析后的结果逐一赋值回原对象,完成属性替换
  • 原代码中o4的.then(function(o){return o})属于冗余代码,可直接删除,不影响功能
  • 注意原代码中a_o数组内的第一个对象有重复键n,JavaScript会自动保留最后一个值,建议编写时避免这种情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 09:47:45