Express基础项目结构搭建
修改配置
创建index.ts
文件在src
目录下书console.log(1111);
如果运行时无法找到index.js
文件
就是并行运行,可能会在编译文件未完成就开始调用了index.js
文件。
使用express
构建一个服务器
npm install express -save
安装类型注解
书写app
服务器并运行npm run dev
import express from "express"; const app = express(); app.get("/", (req, res) => { res.send("hello world"); }); // 启动服务器 app.listen(7001, () => { console.log("server is running"); });
书写类型注解
import express, { Response, Request } from "express"; const app = express(); app.get("/", (req: Request, res: Response) => { res.send("hello world"); }); app.get("/bye", (req: Request, res: Response) => { res.send("bye world"); }); // 启动服务器 app.listen(7001, () => { console.log("server is running"); });
书写路由
创建一个router.ts
import { Router, Request, Response } from "express"; import Crowller from "./crowller"; import DellAnalyzer from "./dellAnalyzer"; const router = Router(); router.get("/", (req: Request, res: Response) => { res.send("hello world !"); }); router.get("/getData", (req: Request, res: Response) => { const secret = "secretKey"; const url = `http://www.dell-lee.com/typescript/demo.html?secret=${secret}`; const analyzer = DellAnalyzer.getInstance(); new Crowller(url, analyzer); res.send("getData Success!"); }); export default router;
使用Ts编写常规express代码遇到的问题
body-parser
引用
$ npm install body-parser
index.ts
import express, { Request, Response } from "express"; import bodyParser from "body-parser"; import router from "./router"; // 问题1: express 库的类型定义文件 .d.ts 文件类型描述不准确 // 问题2: 当我使用中间件的时候,对 req 或者 res 做了修改之后呢,实际上类型并不能改变。 const app = express(); app.use(bodyParser.urlencoded({ extended: false })); app.use(router); app.listen(7001, () => { console.log("server is running"); });
router.ts
import { Router, Request, Response } from "express"; import Crowller from "./crowller"; import DellAnalyzer from "./dellAnalyzer"; const router = Router(); router.get("/", (req: Request, res: Response) => { res.send(`<html> <body> <form method="post" action="/getData"> <input type="password" name="password" /> <button>提交</button> </form> </body> </html>`); }); router.post("/getData", (req: Request, res: Response) => { if (req.body.password === "123") { const secret = "secretKey"; const url = `http://www.dell-lee.com/typescript/demo.html?secret=${secret}`; const analyzer = DellAnalyzer.getInstance(); new Crowller(url, analyzer); res.send("getData Success!"); } else { res.send("password Error!"); } }); export default router;
扩展解决Express的类型定义文件问题
修改index.d.ts
问题1: express 库的类型定义文件 .d.ts 文件类型描述不准确
引入之前的文件的描述内容,对内容进行改变,修正错误的内容。
interface RequestWithBody extends Request { body: { [key: string]: string | undefined; }; }
问题2: 当我使用中间件的时候,对 req 或者 res 做了修改之后呢,实际上类型并不能改变。
类型融合
index.ts
import express, { Request, Response, NextFunction } from "express"; import bodyParser from "body-parser"; import router from "./router"; import request from "superagent"; // 问题1: express 库的类型定义文件 .d.ts 文件类型描述不准确 // 问题2: 当我使用中间件的时候,对 req 或者 res 做了修改之后呢,实际上类型并不能改变。 const app = express(); app.use(bodyParser.urlencoded({ extended: false })); app.use((req: Request, res: Response, next: NextFunction) => { req.teacherName = "dell"; next(); }); app.use(router); app.listen(7001, () => { console.log("server is running"); });
custom.ts
declare namespace Express { interface Request { teacherName: string; } }
登录的开发模块
安装cookie-session
npm install cookie-session --save
npm install @types/cookie-session -D
import { Router, Request, Response } from "express"; import Crowller from "./crowller"; import DellAnalyzer from "./dellAnalyzer"; import fs from "fs"; import path from "path"; const router = Router(); interface RequestWithBody extends Request { body: { [key: string]: string | undefined; }; } router.get("/", (req: RequestWithBody, res: Response) => { const isLogin = req.session ? req.session.login : false; if (isLogin) { res.send(`<html> <body> <a href='/getData'>爬取内容</a> <a href='/showData'>展示内容</a> <a href='/logout'>退出</a> </body> </html>`); } else { res.send(`<html> <body> <form method="post" action="/login"> <input type="password" name="password" /> <button>提交</button> </form> </body> </html>`); } }); router.post("/login", (req: Request, res: Response) => { const { password } = req.body; const isLogin = req.session.login ? req.session.login : false; if (isLogin) { res.send("已经登录过了"); } else { if (password === "123" && req.session) { req.session.login = true; res.send("登录成功!"); } res.send(`password Error!`); } }); router.get("/getData", (req: Request, res: Response) => { const isLogin = req.session.login ? req.session.login : false; if (isLogin) { const secret = "secretKey"; const url = `http://www.dell-lee.com/typescript/demo.html?secret=${secret}`; const analyzer = DellAnalyzer.getInstance(); new Crowller(url, analyzer); res.send("getData Success!"); } else { res.send("请登陆后爬取内容"); } }); router.get("/showData", (req: Request, res: Response) => { const isLogin = req.session ? req.session.login : false; if (isLogin) { try { const position = path.resolve(__dirname, "../data/course.json"); const result = fs.readFileSync(position, "utf-8"); res.json(JSON.parse(result)); } catch (e) { res.send("尚未爬取到内容"); } } }); router.get("/logout", (req: Request, res: Response) => { if (req.session) { req.session.login = undefined; } res.redirect("/"); }); export default router;
统一接口数据结构,优化代码
interface Result { success: boolean; errMsg?: string; data: any; } export const getResponseData = (data: any, errMsg?: string): Result => { if (errMsg) { return { success: false, errMsg, data, }; } return { success: true, data, }; };