Javascript/Node.js 服务器 - 查询 JSON 文件中的数据集以创建 URL

问题描述

应用描述:

我正在尝试创建一个 HTML 模板,该模板接受一组卡片对象并使用其中包含的数据生成一个页面显示卡片列表。对于此列表中的每张卡片,我应该有一个指向该特定卡片的 URL 的链接(例如,http://localhost:3000/cards/that_card's_id),并且链接文本应指明卡片的名称和唯一 ID。

基本上,我会在我的 cmd 栏中输入 node server.js,然后打开谷歌浏览器并在我的地址栏中输入 localhost:3000,它会将我带到显示所有链接的卡片 html 页面。当我点击一张特定的卡片时,它应该会带我到另一个 html 页面,该页面显示显示卡片名称和卡片费用的文本。

问题:

我创建了一个服务器。问题是,当我在地址栏中输入 localhost:3000 时,页面似乎没有加载。我什至无法测试我的代码是否工作,因为页面没有负载。该页面显示“此页面无效”和“本地主机未发送任何数据”。有人告诉我这是因为在我的服务器代码中,我正在侦听请求网址 /cards/cards//cards? 。当我尝试访问 localhost:3000 时,请求 url 是 / ,所以我试图访问一个我没有处理的 url。

server.js:

const pug = require("pug");
const fs = require("fs");
const http = require("http");
const url = require('url')

let cardData = require("./cards.json");
let cards = {}; 
cardData.forEach(card => {
    cards[card.id] = card;
});

//Initialize server
const server = http.createServer(function(request,response) {
    if (request.method === "GET") {
        if (request.url === "/cards") {     
              response.statusCode = 200;
              response.write(pug.renderFile("./views/cards.pug",{ cards: cards }));
              response.end();
        }else if (request.url.startsWith("/cards/")) {
            const paths = request.url.split("/");
            const cardId = paths[2];
            if (cards.hasOwnProperty(cardId)) {
                const targetCard = cards[cardId];
                response.statusCode = 200;
                response.write(
                    pug.renderFile("./views/card.pug",{ card: targetCard })
                );
                response.end();
                return;
            } else {
                response.statusCode = 404;
                response.end();
                return;
            }
        } else if (request.url.startsWith("/cards?")) {
            const params = request.url.split("?");
            const [_,value] = params[1].split("=");
            const limit = parseInt(value);
            if (limit < 1) {
                response.statusCode = 400;
                response.write("Invalid query");
                response.end();
                return;
            }
            const responseCards = Object.values(cards).slice(0,limit);
            response.statusCode = 200;
            response.write(
                pug.renderFile("./views/cards.pug",{ cards: responseCards })
            );
            response.end();
            return;
        }
    } else {
        response.statusCode = 404;
        response.write("UnkNown resource.");
        response.end();
    }
});

//Start server
server.listen(3000);
console.log("Server listening at http://localhost:3000");

cards.json:

[
    {
    "artist":"Arthur Bozonnet","attack":3,"collectible":true,"cost":2,"flavor":"And he can't get up.","health":2,"id":"AT_003","mechanics":["HEROPOWER_damAGE"],"name":"Fallen Hero","rarity":"RARE"
    },{
    "artist":"Dan Scott","cost":4,"flavor":"Is he aspiring or inspiring? Make up your mind!","health":5,"id":"AT_006","mechanics":["INSPIRE"],"name":"Dalaran Aspirant","rarity":"COMMON"
    }
]

cards.pug:

html
    head
        title Cards
body

    div#main
        h1 List of Cards:
        each card in cards
            a(href="/cards/" + card.name) #{card.id}
            br

card.pug:

html
    head
        title #{card.name}
body

    div#main
        h1 Name: #{card.name},Cost: $#(card.cost)

解决方法

我假设您有充分的理由不使用 express 或等效的网络服务器框架,尽管我强烈建议对除最小用例之外的所有用例使用此类工具,但我仍然会尝试根据您当前的设置为您指明正确的方向。

您没有“/”的路由处理程序: 当您转到 localhost:3000 时,服务器挂起的原因是请求处理程序函数对“GET /”没有任何行为。 如果您改为访问 localhost:3000/cards

,您应该会看到您的回复

通过 ID 提供卡片: 通过 id 为卡片提供服务的最佳方法(考虑到技术限制)是这样的(为简洁起见,省略了其余代码):

} else if (request.url.startsWith("/cards/")) {
      const paths = request.url.split("/");
      const cardId = paths[2];
      const card = cards.find((card) => card.id === cardId);

      if (!card) {
        response.statusCode = 404;
        response.end();
        return;
      }

      response.statusCode = 200;
      response.write(pug.renderFile("./views/card.pug",{ card: card }));
      response.end();
      return;
    } 

一般方法 同样,我会认真考虑使用 express,如果您的项目继续增长,它会迫使您将代码分成更易读的片段,并使您的生活大大。举例来说,这就是您的某些代码在 express 中的样子:

const app = require("express")()

app.get("/",(req,res) => {
  return res.sendFile("./views/home.pug")
})

app.get("/cards",res) => {
  return res.sendFile("./views/cards.pug")
});

app.get("/cards/:id",res) => {
  const card = getCard(req.params.id);

  if (!card) {
    return res.sendStatus(404)
  }

  return res.sendFile("./views/cards.pug",{card })
});

此代码不完整 - 但我希望它向您展示您的服务器看起来有多干净!我确实希望它有所帮助 - 祝您编写应用程序好运