创建自己的新冠病毒疫情跟踪器(Node.js+React+TS)
创建自己的新冠病毒疫情跟踪器(Node.js+React+TS)
疯狂的技术宅 前端先锋
翻译:疯狂的技术宅
作者:Krasimir Tsonev
来源:krasimirtsonev.com
正文共:2634 字
预计阅读时间:10 分钟
Create your own Covid-19 data tracker
数据
现在,网络上有数百个新冠疫情跟踪器。首先我想知道他们把数据放在了哪里。经过研究,很快确定了两个主要来源。我最初使用了其中的一个。那就是约翰·霍普金斯大学。他们在 GitHub上发布了一些有用的csv文件。但是,那里的数据每天仅更新一次,所以我开始寻找一些实时服务。我找到了 TheVirusTracker(https://thevirustracker.com/)。我最终使用了他们的 API。他们有每个国家的摘要,但还有时间表。这对我来说更有趣。我没有找到有关请求限制的任何信息,而且似乎没有任何限制信息。
结构
TheVirusTracker 支持 CORS 请求,因此可以将应用构建为完全在浏览器中工作的静态页面。但是,我走了另一条路。如上所述,我最初用的是霍普金斯大学的数据,该数据位于 GitHub上。所以我需要从那里拉取它。最可靠的方法是使用 GitHub 的 contents 端点(https://developer.github.com/v3/repos/contents/)。他们所有端点的速率限制为每小时 60 个请求,为了增加请求数量,需要使用个人访问 token。此类 token 不应被公开共享。所以我不得不写一些后端代码。
新冠疫情数据跟踪器
我的客户端代码正在向 Node.js 进程发出请求。该过程将会获取数据,然后对其进行规范化并返回。后来我更改了数据源,但出于以下三个原因决定保留这个处理流程:
- 我有一个相当不错的用于标准化和缓存数据的层。几乎总是有需要转换数据的需求。无论如何,我都会有这样的代码,所以为什么不将其放在后端,让客户端去使用呢。远程 API 是公共的和免费的,因此,我不应对请求进行重新请求。为了提供高流量,我需要一个缓存层。解决此要求的最基本的方法是实现一个简单的内存缓存。没有服务器,这是不可能的。
- 我已经花费时间编写了一个服务器,不想放弃这项工作。
- 到目前为止,我的代码公开了三个端点。我想与其他开发人员共享这些内容,并让其他人使用规范化和缓存。
几个小时后,我的项目结构变为
新冠疫情数据跟踪器
新冠疫情数据跟踪器前端
做这个项目的一个原因是提高我的 React 和 TypeScript 技能。我已经用这两种出色的技术创建了一些项目,并且出现了一种安装模式。在某个时候,我将必要的配置分组到一个名为 beginning 的程序包中(你可以在这里阅读更多信息:https://krasimirtsonev.com/blog/article/beginning)。因此,我创建了一个空文件夹并运行:
1npx beginning && yarn
这就创建了一个带有 TypeScript 支持的简单 React 应用。
React 生态系统
React 应用本身并不是什么特别的东西。因为这是一个小项目,所以我不需要任何状态管理。一切都只是一个带有几个 hook 的 <App> 组件。
我用 recharts 构建的图表。使用了它的 <LineChart> 组件:
1<LineChart width={900} height={400} data={graphData}> 2 <XAxis dataKey="date" interval="preserveStartEnd" /> 3 <YAxis /> 4 <CartesianGrid /> 5 <Tooltip /> 6 <Legend formatter={(item, entry, idx) => data[idx as number].country} /> 7 <Line 8 key={key} 9 dot={false} 10 type="monotone" 11 dataKey={key} 12 strokeWidth={3} 13 stroke={color} 14 activeDot={{ r: 5 }} 15 legendType="circle" 16 /> 17</LineChart>
结果如下:
用图表制作的新冠疫情数据跟踪图
用图表制作的新冠疫情数据跟踪图
大部分疫情跟踪器都无法按国家/地区过滤数据。通常,此类应用会渲染一大片数据,显然很难过滤信息。我希望自己的跟踪器具有这种过滤功能。我用了另一个流行的软件包 react-tag-autocomplete。它提供了用于管理标签的输入字段。这里的标签是国家名称。
1export default function Builder({ countries, data }: BuilderProps) { 2 const [tags, setTags] = useState<Tag[]>(getTags(countries, data)); 3 const [suggestions, setSuggestions] = useState(getSuggestions(countries)); 4 5 function handleDelete(i: number) { 6 const t = tags.slice(0); 7 t.splice(i, 1); 8 setTags(t); 9 } 10 function handleAddition(tag: Tag) { 11 setTags([...tags, tag]); 12 } 13 14 return ( 15 <> 16 <ReactTags 17 tags={tags} 18 suggestions={suggestions} 19 handleDelete={handleDelete} 20 handleAddition={handleAddition} 21 placeholder="Add a country" 22 /> 23 {tags.length > 0 && ( 24 <Link href={`https://c19stats.now.sh?countries=${tags.map(t => t.name).join(',')}`}> 25 Click here to see stats for {tags.map(t => t.name)} 26 </Link> 27 )} 28 </> 29 ); 30}
为了简化起见,我决定生成一个链接,而不是立即向 API 发出新请求。这样,用户将拥有一个可共享的 URL。
用react-tag-autocomplete制作的新冠疫情数据跟踪器
用react-tag-autocomplete制作的新冠疫情数据跟踪器
该应用的其余部分是几个支持样式的组件,一些输入内容和一个用于请求后端的小型数据层。所有代码都发布在了 github.com/krasimir/covid-19-stats 上。
后端
首先,我想说 Zeit 作为平台是如此的令人愉快。一切都进行得如此顺利。几分钟后,我的网页在 Web 上的工作由Node.js 后端驱动。
我从以下 now.json 文件开始:
1{ 2 "version": 2, 3 "builds": [ 4 { "src": "public/*.*", "use": "@now/static" }, 5 { "src": "api/*.js", "use": "@now/node" } 6 ], 7 "routes": [ 8 { "src": "/api/countries", "dest": "/api/countries.js" }, 9 { "src": "/api", "dest": "/api/index.js" }, 10 { "src": "/(.*)", "dest": "/public/$1" } 11 ] 12}
public 文件夹包含一些静态文件,例如我的 index.html 和生成的 JavaScript bundle。api 目录下的所有内容都是 lambda 函数。例如,在 https://c19stats.now.sh/api/countries 后面,我有
1const countries = require('./countries.json'); 2 3function JSONResponse(res, data, status = 200) { 4 res.setHeader('Content-Type', 'application/json'); 5 res.setHeader('Access-Control-Allow-Origin', '*'); 6 res.statusCode = status; 7 res.end(JSON.stringify(data)); 8} 9 10module.exports = async function(req, res) { 11 JSONResponse(res, countries); 12};
为了访问 TheVirusTracker 的远程服务器,我使用了 superagent。这没有什么不寻常的地方,但能让我方便的粘贴我“惊人”的缓存逻辑:
1const memCache = { 2 lastUpdate: null, 3 data: null, 4}; 5 6const CACHE_TTL = 20; 7 8function getData(noCache) { 9 if (memCache.data && memCache.lastUpdate && typeof noCache === 'undefined') { 10 const now = new Date(); 11 const diff = (now.getTime() - memCache.lastUpdate) / 1000 / 60; 12 if (diff < CACHE_TTL) { 13 return Promise.resolve(memCache.data); 14 } 15 } 16 // normalization of the data 17}
我们首先检查是否存在缓存。memCache 对象的 data 字段保存数据的规范化版本,因此可以直接将其返回(注意 Promise.resolve 调用)。其次,如果有缓存的数据,我们将检查自上次更新以来的分钟数。在这里,我们必须澄清文件的全局作用域中保留的所有内容都将保留。当然,如果我部署了新版本的 lambda 或出于某种原因重新启动了该进程,则缓存将被清除。但是我对此完全满意。这样做的目的是避免不断向远端发出请求。说实话,它的效果很好。https://c19stats.now.sh/ 有时会花费更多时间来加载数据,但是结果页面刷新很快。
创建你自己的新冠疫情追踪器
你可以随时使用 https://c19stats.now.sh/ 上的某些端点。
- 获取特定国家/地区的数据 - /api?countries=US,Italy,Norway
- 获取所有国家/地区的数据 - /api?countries=all
- 获取所有国家/地区的列表 - /api/countries
或者,你可以直接使用 thevirustracker.com/api 的 API。不过如果需要缓存数据的话,则必须自己实现。其余的全由你自己决定。https://c19stats.now.sh/ 的所有代码都是开源的,可在 github.com/krasimir/covid-19-stats 获得。。
- node.js安装+vue-cli安装+创建webpack项目时乱码、特别慢问题+移动端(手机)访问自己的项目
- Node.js入门小记(一)创建自己的node环境
- 【自己的整理】node.js创建静态路由以及Router创建路由
- node.js入门 - 3.创建自己的twitter,准备工作
- Node.js 之一:创建服务
- Node.js 创建第一个应用(2)
- vue.js+node.js运行一个项目时,自己出错的地方
- 基于Node.js,Express,Socket.io创建简单聊天室
- 2018最新React 16+Redux+React Router 4 Node.Js全栈开发招聘App项目实战视频
- node.js之express4.x使用命令创建一个ejs项目及常用命令
- node.js创建一个项目
- node.js 创建HTTP服务器
- node.js中express模块创建服务器和http模块客户端发请求
- C#网页学习之js读取数据库数据并且写入自己创建的表格
- node.js 创建 https 服务器
- 创建node.js一个简单的应用实例
- 安装并创建第一个Node.js程序
- Node.js windows下搭建环境并创建服务器
- 使用webstorm创建一个简单的node.js工程
- node.js学习笔记之创建UDP服务器与客户端