做者:Krasimir Tsonev翻譯:瘋狂的技術宅javascript
原文:https://krasimirtsonev.com/bl...html
未經容許嚴禁轉載前端
如今,網絡上有數百個新冠疫情跟蹤器。首先我想知道他們把數據放在了哪裏。通過研究,很快肯定了兩個主要來源。我最初使用了其中的一個。那就是約翰·霍普金斯大學。他們在 GitHub上發佈了一些有用的csv文件。可是,那裏的數據天天僅更新一次,因此我開始尋找一些實時服務。我找到了 TheVirusTracker。我最終使用了他們的API。他們有每一個國家的摘要,但還有時間表。這對我來講更有趣。我沒有找到有關請求限制的任何信息,並且彷佛沒有任何限制信息。java
TheVirusTracker 支持 CORS 請求,所以能夠將應用構建爲徹底在瀏覽器中工做的靜態頁面。可是,我走了另外一條路。如上所述,我最初用的是霍普金斯大學的數據,該數據位於 GitHub上。因此我須要從那裏拉取它。最可靠的方法是使用 GitHub 的 contents 端點。他們全部端點的速率限制爲每小時 60 個請求,爲了增長請求數量,須要使用我的訪問 token。此類 token 不該被公開共享。因此我不得不寫一些後端代碼。node
個人客戶端代碼正在向 Node.js 進程發出請求。該過程將會獲取數據,而後對其進行規範化並返回。後來我更改了數據源,但出於如下三個緣由決定保留這個處理流程:react
幾個小時後,個人項目結構變爲git
作這個項目的一個緣由是提升個人 React 和 TypeScript 技能。我已經用這兩種出色的技術建立了一些項目,而且出現了一種安裝模式。在某個時候,我將必要的配置分組到一個名爲 beginning 的程序包中(你能夠在這裏閱讀更多信息 "Webpack/TypeScript/React starter kit as of 2020" )。所以,我建立了一個空文件夾並運行:程序員
npx beginning && yarn
這就建立了一個帶有 TypeScript 支持的簡單 React 應用。github
React 應用自己並非什麼特別的東西。由於這是一個小項目,因此我不須要任何狀態管理。一切都只是一個帶有幾個 hook 的 <App>
組件。面試
我用 recharts 構建的圖表。使用了它的 <LineChart>
組件:
<LineChart width={900} height={400} data={graphData}> <XAxis dataKey="date" interval="preserveStartEnd" /> <YAxis /> <CartesianGrid /> <Tooltip /> <Legend formatter={(item, entry, idx) => data[idx as number].country} /> <Line key={key} dot={false} type="monotone" dataKey={key} strokeWidth={3} stroke={color} activeDot={{ r: 5 }} legendType="circle" /> </LineChart>
結果以下:
大部分疫情跟蹤器都沒法按國家/地區過濾數據。一般,此類應用會渲染一大片數據,顯然很難過濾信息。我但願本身的跟蹤器具備這種過濾功能。我用了另外一個流行的軟件包 react-tag-autocomplete。它提供了用於管理標籤的輸入字段。這裏的標籤是國家名稱。
export default function Builder({ countries, data }: BuilderProps) { const [tags, setTags] = useState<Tag[]>(getTags(countries, data)); const [suggestions, setSuggestions] = useState(getSuggestions(countries)); function handleDelete(i: number) { const t = tags.slice(0); t.splice(i, 1); setTags(t); } function handleAddition(tag: Tag) { setTags([...tags, tag]); } return ( <> <ReactTags tags={tags} suggestions={suggestions} handleDelete={handleDelete} handleAddition={handleAddition} placeholder="Add a country" /> {tags.length > 0 && ( <Link href={`https://c19stats.now.sh?countries=${tags.map(t => t.name).join(',')}`}> Click here to see stats for {tags.map(t => t.name)} </Link> )} </> ); }
爲了簡化起見,我決定生成一個連接,而不是當即向 API 發出新請求。這樣,用戶將擁有一個可共享的 URL。
該應用的其他部分是幾個支持樣式的組件,一些輸入內容和一個用於請求後端的小型數據層。全部代碼都發布在了 github.com/krasimir/covid-19-stats 上。
首先,我想說 Zeit 做爲平臺是如此的使人愉快。一切都進行得如此順利。幾分鐘後,個人網頁在 Web 上的工做由Node.js 後端驅動。
我從如下 now.json
文件開始:
{ "version": 2, "builds": [ { "src": "public/*.*", "use": "@now/static" }, { "src": "api/*.js", "use": "@now/node" } ], "routes": [ { "src": "/api/countries", "dest": "/api/countries.js" }, { "src": "/api", "dest": "/api/index.js" }, { "src": "/(.*)", "dest": "/public/$1" } ] }
public
文件夾包含一些靜態文件,例如個人 index.html
和生成的 JavaScript bundle。 api
目錄下的全部內容都是 lambda 函數。例如,在 https://c19stats.now.sh/api/c... 後面,我有
const countries = require('./countries.json'); function JSONResponse(res, data, status = 200) { res.setHeader('Content-Type', 'application/json'); res.setHeader('Access-Control-Allow-Origin', '*'); res.statusCode = status; res.end(JSON.stringify(data)); } module.exports = async function(req, res) { JSONResponse(res, countries); };
爲了訪問 TheVirusTracker 的遠程服務器,我使用了 superagent。這沒有什麼不尋常的地方,但能讓我方便的粘貼我「驚人」的緩存邏輯:
const memCache = { lastUpdate: null, data: null, }; const CACHE_TTL = 20; function getData(noCache) { if (memCache.data && memCache.lastUpdate && typeof noCache === 'undefined') { const now = new Date(); const diff = (now.getTime() - memCache.lastUpdate) / 1000 / 60; if (diff < CACHE_TTL) { return Promise.resolve(memCache.data); } } // normalization of the data }
咱們首先檢查是否存在緩存。 memCache
對象的 data
字段保存數據的規範化版本,所以能夠直接將其返回(注意 Promise.resolve
調用)。其次,若是有緩存的數據,咱們將檢查自上次更新以來的分鐘數。在這裏,咱們必須澄清文件的全局做用域中保留的全部內容都將保留。固然,若是我部署了新版本的 lambda 或出於某種緣由從新啓動了該進程,則緩存將被清除。可是我對此徹底滿意。這樣作的目的是避免不斷向遠端發出請求。說實話,它的效果很好。 https://c19stats.now.sh/ 有時會花費更多時間來加載數據,可是結果頁面刷新很快。
你能夠隨時使用 https://c19stats.now.sh/ 上的某些端點。
或者,你能夠直接使用 thevirustracker.com/api 的 API。不過若是須要緩存數據的話,則必須本身實現。其他的全由你本身決定。 https://c19stats.now.sh/ 的全部代碼都是開源的,可在 github.com/krasimir/covid-19-stats 得到。 。
😷戴好口罩,保證安全的編碼! 😷