如何在这个nodejs代码中执行和处理promise? (用户前后的排行榜排名)

Posted

技术标签:

【中文标题】如何在这个nodejs代码中执行和处理promise? (用户前后的排行榜排名)【英文标题】:How to execute and handle promise in this nodejs code? (the leaderboard rank before and after the user) 【发布时间】:2020-01-28 02:37:20 【问题描述】:

我想在用户前后显示排行榜排名。

文件 leaderboard.js:

exports.leaderboarduser = userName =>
  new Promise((resolve, reject) => 
    const player = user.findOne( userName: userName );
    const next_player = user
      .find( _id:  $ne: player._id , score:  $gte: player.score  )
      .sort( score: 1, userName: 1 )
      .limit(-1)[0];
    const previous_player = user
      .find( _id:  $ne: player._id , score:  $lte: player.score  )
      .sort( score: -1, userName: -1 )
      .limit(-1)[0]
      .then(users => 
        resolve(users);
      )
      .catch(err =>
        reject( status: 500, message: "Internal Server Error !" )
      );
  );

运行时:

(node:18753) UnhandledPromiseRejectionWarning: RangeError [ERR_HTTP_INVALID_STATUS_CODE]:无效状态码:未定义 在 ServerResponse.writeHead (_http_server.js:209:11) 在 ServerResponse.writeHead (/root/game/node_modules/on-headers/index.js:44:26) 在 ServerResponse._implicitHeader (_http_server.js:200:8) 在 write_ (_http_outgoing.js:585:9) 在 ServerResponse.end (_http_outgoing.js:702:5) 在 ServerResponse.send (/root/game/node_modules/express/lib/response.js:221:10) 在 ServerResponse.json (/root/game/node_modules/express/lib/response.js:267:15) 在 leaderboard.leaderboarduser.then.catch.err (/root/game/routes.js:152:42) 在 process._tickCallback (internal/process/next_tick.js:68:7) (node:18753) UnhandledPromiseRejectionWarning: Unhandled Promise 拒绝。此错误源于在异步内部抛出 没有 catch 块的函数,或者通过拒绝一个承诺 不使用 .catch() 处理。 (拒绝 ID:2)(节点:18753)[DEP0018] DeprecationWarning:不推荐使用未处理的承诺拒绝。在 未来,未处理的承诺拒绝将终止 具有非零退出代码的 Node.js 进程。

我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

不确定您是否真的需要多个查询,因为我对您的数据库结构一无所知。这是排序后的代码:

exports.leaderboarduser = (userName) => 
    return new Promise(async (resolve, reject) => 
        try 
            const current_player = await user.findOne( userName: userName );

            const next_playerResult = await user.find( _id:  $ne: player._id , score:  $gte: player.score  ).sort( score: 1, userName: 1 ).limit(1);
            const next_player = next_playerResult[0] || ;

            const previous_playerResult = await user.find( _id:  $ne: player._id , score:  $lte: player.score  ).sort( score: -1, userName: -1 ).limit(1);
            const previous_player = previous_playerResult[0] || ;
            resolve([current_player, next_player, previous_player]);        // change the order as per requirement
            // OR better send an object like: resolve( current_player, next_player, previous_player );
         catch (err) 
            reject(err);
        
    );

问题是您没有正确调用异步函数。也没有 catch 块来处理错误。我在 Promise 中使用了 async/await 来处理异步数据库调用。然后在您的项目中的某个地方,您可以将此函数称为:

leaderboarduser('testName')
    .then((users) => 
        console.log("users are: ", users);
    ...
    // do something with users
)
    .catch((err) => 
        console.log("Error: ", err);
    ...
    // handle error
);

mongoose 中的 limit() 也是用来限制记录数的。由于在您的情况下您只需要一条记录,因此您应该通过 1 而不是 -1

希望这会有所帮助:)

【讨论】:

Never pass an async function as the executor to new Promise!

以上是关于如何在这个nodejs代码中执行和处理promise? (用户前后的排行榜排名)的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 NodeJS 在本地测试 AWS Lambda 处理程序?

对fs异步读取文件的理解

如何提高NodeJS程序的稳定性

nodejs如何判断数据库操作是不是执行完毕

nodeJs无法执行js文件?

如何使用消息队列在 Node JS 中执行长事件处理?