使用正确的后备路由结构从Node.js中的异步调用传递数据的最佳实践

我有一个请求函数,该函数调用一个端点并从中获取数据。然后我将此数据传递到HBS模板进行渲染,但是由于异步性,传递给模板的数组为空。什么是正确的方法。请帮忙。下面的代码段。

app.get("/verifier", keycloak.protect('verifier'), (req, res) => {  
  cirRes = cirJSON.parse(cirJSON.stringify(res))
  //the req object is a circular object so you cannot convert it to json normaly wihtout data loss.
  allUser = []
  access_token = cirRes.req.kauth.grant.access_token.token
  var options = { method: 'GET',
  url: 'http://localhost:8080/auth/admin/realms/create_user_realm/users',
  headers: 
   { 
     'Content-Type': 'application/x-www-form-urlencoded',
     Host: 'localhost:8080',
     Accept: '*/*',
     Authorization: `Bearer ${ access_token }` } }
  request(options, function (error, response, body) {
    if (error) throw new Error(error);
      data = JSON.parse(body)
      for (user in data){
       allUser.push(data[user])
      } 
      //console.log(allUser)
  })
  if (res.statusCode != 200) {
    res.redirect('/logout')
  }
  console.log(allUser)
  res.render('verifier', {"users": allUser})
})

在上面的代码中,allUser结果是一个空数组。

编辑>>>>

This question was closed given the answer in this thread. How do I return the response from an asynchronous call? It covers different ways to make asynchronous requests.

经历同样的我在代码中做了这个改变

app.get("/verifier", keycloak.protect('verifier'), (req, res) => {  
  cirRes = cirJSON.parse(cirJSON.stringify(res))
  //the req object is a circular object so you cannot convert it to json normaly wihtout data loss.
  //console.log(cirRes.req.kauth.grant.access_token.token)
  allUser = []
  access_token = cirRes.req.kauth.grant.access_token.token
  var options = { method: 'GET',
  url: 'http://localhost:8080/auth/admin/realms/create_user_realm/users',
  headers: 
   { 
     'Content-Type': 'application/x-www-form-urlencoded',
     Host: 'localhost:8080',
     Accept: '*/*',
     Authorization: `Bearer ${ access_token }` } }
  request(options, function (error, response, body) {
    if (error) { throw new Error(error) }
      data = JSON.parse(body)
      for (user in data){
       allUser.push(data[user])
      } 
      //console.log(allUser)
      res.render('verifier', {"users": allUser})
    })
  if (res.statusCode != 200) {
    res.redirect('/logout')
  }
})

这可以正常工作,但是根据nodeJS的最佳实践以及在nodeJS中的最佳实践是正确的,因此即使调用发生错误,也可以使用一些后备机制来呈现。

评论
  • eet
    eet 回复

    Move your res.render() and res.redirect() calls so they are inside the callback function of your request() call. That's how you use asynchronously provided information in express when you want to send it to a user's browser or API client.

  • ysunt
    ysunt 回复

    这是完美的。您需要在try-catch块中添加选项变量。

    try{
    var options = { method: 'GET',
      url: 'http://localhost:8080/auth/admin/realms/create_user_realm/users',
      headers: 
       { 
         'Content-Type': 'application/x-www-form-urlencoded',
         Host: 'localhost:8080',
         Accept: '*/*',
         Authorization: `Bearer ${ access_token }` } }
      request(options, function (error, response, body) {
        if (error) { throw new Error(error) }
          data = JSON.parse(body)
          for (user in data){
           allUser.push(data[user])
          } 
          //console.log(allUser)
          res.render('verifier', {"users": allUser})
        })
      if (res.statusCode != 200) {
        res.redirect('/logout')
      }
    
    }catch(e){
      throw(e);
    }