在呈现页面之前等待挂起的 Promise

Wait for pending Promises before rendering the Page

我目前正在为 node.js 中的 Twitch 社区开发一个网络项目。我正在使用 Twitch API 接收个人资料图片,并将它们与其他信息一起添加到对象数组中,然后再呈现页面。不幸的是,当页面呈现时,我只会得到个人资料图片 URL 的未决承诺。在页面呈现后将近一毫秒,我得到了关于 PB-Links 的控制台日志,所以它运行得很快,所以我认为 ajax 没有意义。在脚本继续呈现页面之前是否有可能等到承诺加载完毕?

提前致谢

async function getStreamersPB(streamerName){
  var streamer = await twitch.getUsers(streamerName);
  var streamerPBURL = await streamer.data[0].profile_image_url;


  console.log(streamerPBURL);
}

...

router.get('/', (req, res) => {

  var streamer = [];
    con.query("SELECT * FROM xxx",  function (err, result) {
    if (err) {
      console.log(err);
    }
    if (result.length !== 0){
      for (let i = 0; i < result.length; i++) {
        let streamObj = {
          "id": result[i].id,
          "name": result[i].name,
          "website": result[i].website.toLowerCase(),
          "status": result[i].status,
          "rang": result[i].rang,
          "userPB": getStreamersPB(result[i].name)
        }
        console.log(streamObj);
        streamer.push(streamObj);
    }}});

    con.query("SELECT * FROM xxx WHERE xxx = '" + xxx + "'", function (err, result) {
    if (err) {
      console.log(err);
    } if(result.length === 1){
    res.render('home', {
      message: result[0].twitchName,
      userID: result[0].id,
      streamer: streamer
    });

...

这是我的控制台日志:

{
  id: 1,
  name: 'xxx',
  website: 'xxx',
  status: 0,
  rang: 1,
  userPB: Promise { <pending> }
}
https://static-cdn.jtvnw.net/...xxx

您可以先使用css隐藏页面,然后当您的个人资料图片加载后,使用javascript更改css并显示页面。

正如 slebetman 所提到的,您必须等待异步函数调用,否则您将向您的客户发送待处理的承诺。这是修改后的代码。

router.get('/', (req, res) => {

  var streamer = [];

  // This function has been marked as async so we can use await in it.
  con.query("SELECT * FROM xxx", async function (err, result) {

    if (err) {
      console.log(err);
    }

    if (result.length !== 0) {
      for (let i = 0; i < result.length; i++) {

        let streamObj = {
          "id": result[i].id,
          "name": result[i].name,
          "website": result[i].website.toLowerCase(),
          "status": result[i].status,
          "rang": result[i].rang
        }

        // getStreamersPB is an asynchronous method which you must await.
        streamObj.userPB = await getStreamersPB(result[i].name);

        console.log(streamObj);
        streamer.push(streamObj);
      }
    }

    // I moved this query to inside the callback for the first query
    // to ensure this query happens after the first one. Originally,
    // both `con.query` calls were being invoked at the same time, so
    // there's no garuntee in what order they execute.
    con.query("SELECT * FROM xxx WHERE xxx = '" + xxx + "'", function (err, result) {
      if (err) {
        console.log(err);
      } if (result.length === 1) {
        res.render('home', {
          message: result[0].twitchName,
          userID: result[0].id,
          streamer: streamer
        });
      }
    });

  });

});

由于您收到 Dylan 的回答错误,请将异步添加到第一个 com.query 函数。

router.get('/', async (req, res) => {

  var streamer = [];
    con.query("SELECT * FROM xxx", async function (err, result) {
    if (err) {
      console.log(err);
    }
    if (result.length !== 0){
      for (let i = 0; i < result.length; i++) {
        
        let streamObj = {
          "id": result[i].id,
          "name": result[i].name,
          "website": result[i].website.toLowerCase(),
          "status": result[i].status,
          "rang": result[i].rang
        }

        // getStreamersPB is an asynchronous method which you must await.
        streamObj.userPB = await getStreamersPB(result[i].name);

        console.log(streamObj);
        streamer.push(streamObj);
    }}});

    con.query("SELECT * FROM xxx WHERE xxx = '" + xxx + "'", function (err, result) {
    if (err) {
      console.log(err);
    } if(result.length === 1){
    res.render('home', {
      message: result[0].twitchName,
      userID: result[0].id,
      streamer: streamer
    });

}

我修好了!我忘了在函数中加入 return 语句!

非常感谢大家的回答和帮助!!!