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

Node.js渲染页面前如何等待Pending状态的Promises执行完成

问题解决思路

你的代码存在几个核心问题:

  1. getStreamersPB 是async函数,默认返回Promise对象,且缺少返回语句,你直接将函数返回值赋值给userPB,存储的自然是处于pending状态的Promise而非实际的头像URL。同时该函数中对profile_image_url加了多余的await,该值是接口返回对象的普通属性,不是异步Promise,不需要等待。
  2. 两个数据库查询采用回调写法,属于异步并行执行,大概率第二个查询会先返回直接触发页面渲染,此时第一个查询的主播列表还未处理完成,头像请求更是没有返回结果。
  3. 循环中发起的多个头像异步请求没有等待全部完成就继续执行后续逻辑,导致最终渲染时数据未就绪。

修复步骤

1. 修正头像获取函数

补全返回值,移除多余的await:

async function getStreamersPB(streamerName){
  const streamer = await twitch.getUsers(streamerName);
  const streamerPBURL = streamer.data[0].profile_image_url;
  console.log(streamerPBURL);
  return streamerPBURL; // 新增返回头像URL
}

2. 改写路由逻辑,统一异步流程

建议优先使用支持Promise的数据库驱动(比如mysql2/promise),配合async/await和Promise.all等待所有异步请求完成后再渲染页面,同时使用参数化查询避免SQL注入漏洞:

const mysql = require('mysql2/promise');
// 初始化数据库连接逻辑保持不变,仅调整路由写法
router.get('/', async (req, res) => {
  try {
    // 第一步:查询主播列表
    const [streamerResult] = await con.query("SELECT * FROM xxx");
    let streamer = [];
    if (streamerResult.length !== 0) {
      // 批量生成所有头像请求的Promise数组
      const promiseList = streamerResult.map(async (item) => {
        const pbUrl = await getStreamersPB(item.name);
        return {
          id: item.id,
          name: item.name,
          website: item.website.toLowerCase(),
          status: item.status,
          rang: item.rang,
          userPB: pbUrl
        }
      });
      // 等待所有头像请求全部完成
      streamer = await Promise.all(promiseList);
    }
    // 第二步:查询用户信息
    const [userResult] = await con.query("SELECT * FROM xxx WHERE xxx = ?", [xxx]); // ?为参数占位符,自动转义避免SQL注入
    if (userResult.length === 1) {
      // 所有数据准备完成后再渲染页面
      res.render('home', {
        message: userResult[0].twitchName,
        userID: userResult[0].id,
        streamer: streamer
      });
    }
  } catch (err) {
    console.log(err);
    res.status(500).send('服务器内部错误');
  }
});

如果你不想更换数据库驱动,也可以手动封装一个Promise版本的查询方法:

function queryAsync(sql, params) {
  return new Promise((resolve, reject) => {
    con.query(sql, params, (err, result) => {
      if (err) return reject(err);
      resolve(result);
    })
  })
}

后续直接用await queryAsync(sql, 参数)调用即可,效果和上面一致。


优势

  • 全程在服务端处理完所有数据请求,不需要前端额外发AJAX拉取头像,符合你的需求
  • Promise.all会并行处理所有头像请求,不会额外增加太多接口耗时
  • 统一的错误捕获逻辑,避免未处理的异步异常导致服务崩溃

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 07:15:03