异步/等待请求在 Passport 策略中的应用

4
我已经到处寻找能解决这个问题的答案,并尝试了不同的建议,但仍然无法解决。我正在使用passport中的steam API策略,在创建新的SteamStrategy之后,我有一个回调函数来处理我的MongoDB集合。基本上,我只是检查当前登录的用户是否在数据库中,如果不在,则创建一个新的User并将其.save()到mongoDB中。这一切都很好,直到我决定向steam API请求一些附加的用户信息以存储到新的User中。然而,当我尝试将request()保存到一个变量中并console.log()变量时,它总是显示为null。我知道这是因为它是异步运行的,但这就是为什么我使用await的原因,但没有成功。我还尝试实现callback-hell类型的解决方案,但在最终语句"return done(null, user);"中遇到了一些严重的作用域问题。总之,如果有人能解释并提供解决方案,那将会很棒,谢谢!
passport.use(
      new SteamStrategy(
        {
          returnURL: keys.returnURL,
          realm: keys.realm,
          apiKey: keys.steamAPI,
          proxy: true
        },
        async function(identifier, profile, done) {
          const existingUser = await User.findOne({
            steamInfo: { id: profile._json.steamid }
          });

          if (existingUser) {
            middleware.updateMongo(existingUser);
            return done(null, existingUser);
          }

          ////////////////////////THE PROBLEM STARTS HERE/////////////////////
          const steamURL = "hiding url for post";

          const info = await request(steamURL, function(error, response, body) {
            if (!error && response.statusCode == 200) {
              console.log(JSON.parse(body)); //THIS PRINTS OUT THE INFO PERFECTLY
              return JSON.parse(body);
            }
          });


          console.log(info); //THIS WILL ALWAYS SHOW AS NULL OR UNDEFINED

          const user = await new User({
            steamInfo: {
              id: profile._json.steamid,
              persona: info.personaname,
              profileUrl: info.profileurl,
              avatar: info.avatarmedium,
              personaState: info.personastate,
              visibility: info.communityvisibilitystate,
              countryCode: info.loccountrycode
            },
            collectedInfo: { rank: "", reports: "0" }
          }).save();

          return done(null, user);
        }
      )
    );
1个回答

2
问题在于您同时使用了await和回调函数,这是不应该的。此外,request模块不使用 promises - 您需要使用request-promise代替,它基本上是一个围绕request模块的包装器,让您可以使用 promises。
const request = require("request-promise");

let info = {};
try {
  info = await request(steamURL);
  console.log(info);
}
catch (err) {
  /* Handle error */
}

我该如何在没有回调函数的情况下返回主体? - Phil
@PhillipR Promise会解析响应体。如果您想要响应代码等更多选项,您需要添加更多选项,但我不记得您现在需要哪些选项。请查看文档。 - spicypumpkin
@PhillipR 基本上,在我的代码中 info 是响应体。 - spicypumpkin
非常感谢!它起作用了。只需要两行代码(真的),而我已经花了2个小时来尝试解决它。-_- - Phil
1
@PhillipR 哈哈,那是常有的事。请注意许多 Node 的模块都有单独的 Promise 化模块(比如 request-promisechai-as-promised),因此如果文档没有明确说明函数返回 Promise,则应该寻找这些模块。 - spicypumpkin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接