首页 > 解决方案 > Node.js - 将 JSON 数据解析为 PUG 模板

问题描述

我正在尝试将一些 JSON 数据解析为一些称为 homeCards 的元素。我使用 Axios 来请求 JSON 数据并有一个 for 循环来遍历它。我将所需的字段存储在标题和描述变量中,并将这些变量传递给 homeCards。我的问题是我的标题和描述变量存在于我的 axios 函数中,当我尝试将这些值分配给在其范围之外声明的 homeCards 时,它找不到它们。如果我在 Axios 函数中移动我的 homeCard 声明,那么我将无法在文件底部的渲染函数中调用 homeCards。我该如何解决这个问题?有没有更简单的方法来做到这一点?

var express = require('express');
var router = express.Router();
var title = "title"
var description = "description"

const axios = require('axios');

axios({
  url: "https://api-v3.igdb.com/games",
  method: 'GET',
  headers: {
      'Accept': 'application/json',
      'user-key': 'user-key'
  },
  data: "fields name,summary,popularity;sort popularity desc;limit 4;"
})
  .then(response => {
      let r = response.data;
      for (i=0; i<r.length; ++i){
          title = r[i].name;
          description = r[i].summary;
          console.log(title, description);
      }
    })
  .catch(err => {
      console.error(err);
  });


var homeCards = [
        {
          title: title,
          description: description,
        },
        {
          title: title,
          description: description,
        },
        {
          title: title,
          description: description,
        },
        {
          title: title,
          description: description,
        },
        ]

/* GET home page. */
router.get('/', (req, res, next) => {
  res.render('index', { pageId: 'index',
                        title: 'Homepage',
                        cards: homeCards
    });

});
/*GET consoles page. */
router.get('/consoles', (req, res, next) => {
    res.render('consoles', { pageId:'consoles',
                             title: 'Consoles', });
});
/*GET about page. */
router.get('/about', (req, res, next) => {
    res.render('about', { pageId:'abuot',
                          title: 'About' });
});

module.exports = router;

如果我在 router.get 调用中移动相关代码,如下所示:

    /* GET home page. */
router.get('/', (req, res, next) => {
  res.render('index', { pageId: 'index',
                        title: 'Homepage',
                        cards: homeCards
    });

  const axios = require('axios');

  axios({
    url: "https://api-v3.igdb.com/games",
    method: 'GET',
    headers: {
        'Accept': 'application/json',
        'user-key': 'feaa948461a62d2965098834275aaa2f'
    },
    data: "fields name,summary,popularity;sort popularity desc;limit 4;"
  })
    .then(response => {
        let r = response.data;
        for (i=0; i<r.length; ++i){
            title = r[i].name;
            description = r[i].summary;
            console.log(title, description);
        }
      })
    .catch(err => {
        console.error(err);
    });
    var homeCards = [
        {
          title: title,
          description: description,
        },
        {
          title: title,
          description: description,
        },
        {
          title: title,
          description: description,
        },
        {
          title: title,
          description: description,
        },
        ]

});

我收到以下错误:index.pug:19 17| div(class="card-deck") 18| 如果 pageId === 'index' > 19| 卡片中的每个项目 20| +horizo​​ntalCard(item.title,item.imgSrc, item.imgAlt, item.link, item.description) 无法读取未定义的属性“长度”。这是有问题的哈巴狗文件

 //- views/index.pug
extends layout

mixin horizontalCard(title, imgSrc, imgAlt, link, description)
    div(class="card bg-secondary mb-3" style="min-width: 230px; max-width: 540px;")
        img(src=imgSrc class="card-img" alt=imgAlt)
        div(class="card-body")
            h5(class="card-title")= title
            p(class="card-text")= description
            p(class="card-text")
                small(class="text-muted")
                a(rel="noreferrer noopener" href=link target="_blank") Visit Website

block content
    h1= title
    P Most Popular Games
    div(class="card-deck")
        if pageId === 'index'
            each item in cards
                +horizontalCard(item.title,item.imgSrc, item.imgAlt, item.link, item.description)

如果我在 .then(response) 块内移动 router.get 调用,如下所示:

    axios({
  url: "https://api-v3.igdb.com/games",
  method: 'GET',
  headers: {
      'Accept': 'application/json',
      'user-key': 'feaa948461a62d2965098834275aaa2f'
  },
  data: "fields name,summary,popularity;sort popularity desc;limit 4;"
})
  .then(response => {
      /* GET home page. */
    router.get('/', (req, res, next) => {
      res.render('index', { pageId: 'index',
                        title: 'Homepage',
                        cards: homeCards
        });

    });
    var homeCards = [
        {
          title: title,
          description: description,
        },
        {
          title: title,
          description: description,
        },
        {
          title: title,
          description: description,
        },
        {
          title: title,
          description: description,
        },
        ]
    let r = response.data;
    for (i=0; i<r.length; ++i){
        var title = r[i].name;
        var description = r[i].summary;
        console.log(title, description);
      }
    })
  .catch(err => {
      console.error(err);
  });

homecards什么都不显示

标签: javascriptnode.jsjsonpug

解决方案


在您的代码中,该axios({...}).then()块在主代码(分配和调用)完成执行。这就是 Node.js(和一般的 JavaScript)异步调用的工作方式,设计如下:axios 进行网络调用,因此它以 promise 的形式返回其结果,在调用者函数代码执行后得到解决。homeCardsrouter.get

将所有内容(包括router.get调用)移动到 axios.then处理程序中是一种选择。如果您以 Node.js 8+ 为目标,另一种选择是使用async/await模式以同步方式编写异步代码。这与将所有逻辑放在 axios 处理程序中基本相同.then,但看起来要好得多。

async function init() {
  const response = await axios({...});
  homeCards = ...;
  router.get(...);
  ...
}

init().catch(err => {
  console.error(err);
});

推荐阅读