Promise.all() 返回未定义的 Promise <Pending> 数组,尽管类似的解决方案返回成功的替代方案

Posted

技术标签:

【中文标题】Promise.all() 返回未定义的 Promise <Pending> 数组,尽管类似的解决方案返回成功的替代方案【英文标题】:Promise.all() returns undefined array of Promise <Pending>'s, despite similar solutions returning successful alternatives 【发布时间】:2019-10-03 14:48:13 【问题描述】:

我正在构建一个网络应用程序,允许用户查看项目仪表板,这些项目又具有单独的部分(a、b 和 c),仪表板将显示为完整 (o) 或不完整 (x)如下图所示。这允许用户直接导航到缺少信息的页面,因为需要项目的所有信息才能进入下一阶段。

Item | a | b | c | Next Stage?
------------------------------
abc  | x | o | x | No
def  | x | x | x | No
ghi  | o | o | o | Yes

在每个项目(例如 abc)中,它可以有许多子项目,这些子项目必须全部完成才能将该项目的 a、b 或 c 部分标记为完成。这是通过一系列嵌套的承诺来实现的,这些承诺在更新子项时更新“完整性”变量。但是,当尝试将变量从子项(a's、b's、c's)的范围传输到父项(abc、def、ghi)时,会出现问题。我以前使用嵌套的 Promise 没有实现 async/await 并且因为这是该项目范围内的 Promise 的最终用法,我犹豫采用不同的方式来解决这个问题(但我不反对它)。

当前实施:

exports.loadDashboard = (req, res, next) => 
Item.find()
.where("user").equals(req.session.user)
.select()
.exec()
.then(docs => 
    const response = 
        items: docs.map(doc => 
            const aPromise = Feature.find().where("projectID").equals(doc._id).select("aComplete").exec();
            const bPromise = Feature.find().where("projectID").equals(doc._id).select("bComplete").exec();
            const cPromise = Feature.find().where("projectID").equals(doc._id).select("cComplete").exec();
            Promise.all([aPromise, bPromise, cPromise]).then(result => 
                return
                    _id: doc._id,
                    user: doc.user,
                    aComplete: result[0],
                    bComplete: result[1],
                    cComplete: result[2]
                
            // )
        
    ),
    userSessionID: req.session.user   
    
    if(req.session.user != null)
        console.log(response);
        res.render("dashboard", response);
    else
        res.redirect("login");
    
)
.catch(err=>
    console.log(err);
    res.status(500).json(
        error: err
    );
);

...授予response 的:

  items: [ undefined, undefined, undefined ],
 userSessionID: '1' 

这些未定义的项目是Promise &lt;Pending&gt; 类型,类似的问题已经以类似的方式解决了,但这次我很卡住。我的问题是,是否有可能在不深入研究 async/await 的情况下解决这个问题,或者我应该硬着头皮,如果是这样,我将非常感谢提供的任何帮助。

感谢阅读

【问题讨论】:

不要尝试在响应对象中构建所有内容。做你的Promise.all,然后从它的then 回调,建立你的回应。否则,您甚至在完成之前就返回您的回复。 谢谢@Keith,虽然我不确定我是否理解 - 我已经在Promise.allthen 回调中建立了我的回复,不是吗?我看不到如何在调用它们之前调用Promise 函数,因为我需要doc 范围来获取_ids? 【参考方案1】:

这里发生了很多事情,如果可能的话,切换到使用 async/await 而不是使用 Promises,因为这是使您的代码难以维护的主要原因之一。我相信您可能只需要实际返回正确的值。

您的 .map 函数没有返回任何内容,这可能是您收到 [undefined, undefined, undefined] 的主要原因。

exports.loadDashboard = (req, res, next) => 
// don't use "where", if you don't have to
Item.find(user: req.session.user)
.exec()
.then(docs => 
  const items = docs.map(doc => 
            const aPromise = Feature.find().where("projectID").equals(doc._id).select("aComplete").exec();
            const bPromise = Feature.find().where("projectID").equals(doc._id).select("bComplete").exec();
            const cPromise = Feature.find().where("projectID").equals(doc._id).select("cComplete").exec();
            // THIS IS WHERE I ADDED THE RETURN!
            return Promise.all([aPromise, bPromise, cPromise])
             .then(result => 
                return 
                    _id: doc._id,
                    user: doc.user,
                    aComplete: result[0],
                    bComplete: result[1],
                    cComplete: result[2]
                
            
       ))
  return Promise.all(items);
)
.then(items => 
    const response = 
       userSessionID: req.session.user,
       items
    ;
    // also check if .user is undefined, the null check is then optional
    if(!req.session.user || req.session.user === null)
      return res.redirect("login");
    
    console.log(response);
    return res.render("dashboard", response);
).catch(error => 
  console.log(error);
  res.status(500).json(error);
);

看看情况如何。我相信可能仍然存在一些问题,但该大纲应该会让您更容易使用它。

【讨论】:

绝对惊人,这完全符合我的预期。非常感谢 BenSower 和 @Keith 的投入和帮助! 没问题。正如我已经提到的,我建议您查看更新的 async/await 语法,这使得编写此代码更容易和更清晰。 我一定会的,这个项目是鲁莽地跳入 NoSQL 和异步代码的未知世界,但至少下次我会(稍微)准备好!

以上是关于Promise.all() 返回未定义的 Promise <Pending> 数组,尽管类似的解决方案返回成功的替代方案的主要内容,如果未能解决你的问题,请参考以下文章

具有不同返回类型的 Promise.all [关闭]

并行承诺的自定义错误处理

理解Promise.all,Promise.all与Promise.race的区别,如何让Promise.all在rejected后依然返回resolved状态

如何返回 Promise.all 获取 api json 数据?

Promise.all()使用方法

promise.all 不返回实际结果