在Windows,Mac,Linux中快速安裝配置Node.js環境,並安裝VSCode, 完成Web端恆生交易日接口的圖形化展示

編程課應該怎麼製作?

編程的樂趣應來自實用主義,我大學本科第一門Java編程課,幾乎勸退了所有同學,因爲那些教學代碼不實用且無趣,一點圖形化的內容都沒有,而實用的編程課應早早展現圖形化的成果, 於是我選擇開一門前後端齊頭並進的全棧課程, 本課程將從零開始, 教授大量實用的圖形化案例, 並給出完整源碼.本文涉及到的代碼完全開源在Github,地址: https://github.com/zhaoolee/it/tree/main/src/Class001

本文是基於 Node.js 和 JavaScript的全棧編程教程, 雖然Node.js 和 JavaScript都被人稱爲js, 編程語法也近似, 但兩者的確是兩門不同的語言;

JavaScript是前端編程語言, 運行在瀏覽器, 可以用來做各種網頁特效, 數值運算, 以及數據請求, JavaScript的獨特之處在於, 它沒有競爭對手, 瀏覽器內可以運行的編程語言就它一個, 只要學前端, 就離不開Node.js;

Node.js 是後端編程語言, 也就是傳統意義的編程語言, Node.js可以讀取本地計算機的文件, 進行極爲複雜的運算, 做機器學習, 深度學習, 與Python, C, C++, GoLang等語言算得上競爭對手, Node.js的特色是與JavaScript的語法極爲相似, 學會了JavaScript的人, 再去學習Node.js, 會顯得非常容易;

本門課程目標是培養一批會寫碼, 能整活兒的全棧工程師, 全棧工程師也可以被稱作全乾工程師, 技能豐富, 能獨立完成產品的研發, 學完這門課程, 你也可以寫出自己的小程序.

學編程, 需要讓電腦可以運行代碼, 想要運行代碼,則需要安裝編程語言的開發包

JavaScript代碼可以在瀏覽器直接運行, 安裝Chrome瀏覽器即可.

Chrome下載地址: https://google.cn/chrome

Node.js 代碼需要從官網下載開發包並安裝

Node.js官網下載頁面

https://nodejs.org/zh-cn/download/

  • Windows安裝包

https://nodejs.org/dist/v16.13.0/node-v16.13.0-x64.msi

  • 通過以上鍊接, 下載安裝包, 右鍵, 安裝(也可以直接雙擊安裝)
  • NEXT
  • 同意條款,下一步
  • 保存默認安裝位置, 下一步

默認安裝位置爲 C:\Program Files\nodejs\

  • 下一步
  • 下一步
  • 開始安裝
  • 允許更改
  • 等待
  • 完成
  • 搜索PowerShell 並使用管理員身份打開
  • 輸入 node -v , 如果能查看到Node.js的版本, 則說明安裝成功了

以上是Windows 安裝Node.js的傳統方案,現在微軟官方推出了WSL (Windows Subsystem for Linux)方案,也就是在Windows裏安裝一個Linux子系統, 可以在Windows使用Linux中超好用的zsh工具(自動路徑補全,自動命令提示,文本多彩高亮), 效果驚豔,強烈推薦! 當你用過了zsh, 你就再也無法忍受Windows超級難用的命令行工具了。

Windows安裝 WSL教程 程序員福音!Win10下使用oh-my-zsh全攻略,讓Win10開發更順滑…

安裝好WSL後, 按照本文Linux安裝Node.js部分,直接安裝Node.js即可,只需幾行命令,方便又快捷。

另外說明一下,安裝好Linux後,我們的程序可以直接在Linux中運行,Linux和Windows相當於兩臺機器,二者有獨立的IP, 我們可以通過在Linux中運行 ifconfig | grep inet 來查看Linux的ip, 後文中默認的 localhost:3000, 也應該修改爲 Linux的ip:3000

如果你想更多瞭解Linux命令,可以查看這個網站 Linux清單

macOS 安裝Node.js

下載安裝包: https://nodejs.org/dist/v16.13.0/node-v16.13.0.pkg

  • 打開安裝包
  • 繼續
  • 繼續
  • 同意(只能同意,不同意就不讓用)
  • 繼續
  • 安裝
  • 驗證身份,進行安裝
  • 安裝成功, 關閉對話框
  • 安裝包建議留一份,重裝可以用
  • 打開終端
  • Linux 安裝Node.js

Linux 做編程其實是最爽的,不用考慮Windows亂七八糟的路徑問題,開源免費。

如果你追求顏值,比較推薦的Linux桌面發行版是Deepin,Deepin是一款國產Linux, 本地化做的很棒,Deepin鏡像免費下載地址 https://www.deepin.org/zh/download/ 清華大學Deepin鏡像源直接下載鏈接 https://mirrors.tuna.tsinghua.edu.cn/deepin-cd/20.2.4/deepin-desktop-community-20.2.4-amd64.iso

在Linux安裝Node.js的操作,我在Deepin上完成

  • 打開終端

Linux安裝Node.js僅需幾行命令

cd /opt/
sudo wget https://nodejs.org/dist/v16.13.0/node-v16.13.0-linux-x64.tar.xz
sudo tar xvf node-v16.13.0-linux-x64.tar.xz
sudo echo "export NODE_HOME=/opt/node-v16.13.0-linux-x64" >> ~/.bashrc
sudo echo "export PATH=\$NODE_HOME/bin:\$PATH" >> ~/.bashrc
source ~/.bashrc
node -v
  • 獲取安裝包並解壓安裝包

安裝VSCode

VSCode是微軟推出的一款代碼編輯器,開源免費,功能強大,Windows, macOS, Linux均有對應的版本,且功能一致。

VSCode 官網: https://code.visualstudio.com/

下載頁面 https://code.visualstudio.com/Download

下載VSCode 安裝包後,雙擊安裝即可。

  • 打開VSCode軟件, 安裝中文語言包

安裝完成後,重啓VSCode即可生效

VSCode是一個神奇的軟件,它不僅可以寫代碼,還可以搞各種其妙的小插件,比如可以輸入 zhihu 搜索知乎插件並安裝

安裝成功後,即可在寫代碼累的時候,刷刷知乎,放鬆一下(職業程序員摸魚神器)

如果你是個追番達人,可以搜索插件 daily-anime, 安裝成功後,使用Alt+L組合鍵,即可開始享用

我們來寫第一段代碼

  • 在VSCode中新建文件
  • 保存文件到桌面
  • 在HelloWorld.js 中加入以下代碼
const http = require('http');

http.createServer(function (request, response) {

    // 發送 HTTP 頭部 
    // HTTP 狀態值: 200 : OK
    // 內容類型: 純文本 text/plain
    // 編碼類型: utf-8
    response.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});

    // 返回內容
    let content = "來自互聯網之神的祝福\n\n";

    // 循環十次,不斷增加返回內容
    for(let i = 0; i < 10; i++){
        content = content + "Hello World==>" + i + "\n"
    }


    // 發送響應數據 "Hello World"
    response.end(content);

}).listen(8888);

// 終端打印如下信息
console.log('請用瀏覽器訪問 http://127.0.0.1:8888/');
  • 新建終端
  • 右鍵頂部的標籤,左鍵點擊複製路徑
  • 輸入命令
  • 按回車鍵, 運行程序
  • 訪問 http://127.0.0.1:8888

Node.js 程序運行成功!

使用動態的數據源

一套完整的程序,可以分爲客戶端和服務端,客戶端與服務端通過 API (Application Programming Interface,應用程序接口, 簡稱接口)進行數據交互,很多金融雲服務商,會提供一些現成的 API 進行售賣,有些按時間付費,有些按使用(調用)次數付費,我們這裏用恆生雲交易日曆API進行一波調用演示。

API 文檔地址: https://www.hs.net/openplat-front/service/serviceDetail/983

通過文檔截圖可知,我們必填的請求參數,有三個,分別是 證券市場代號secu_market開始日期 strat_date, 結束日期 end_date

如何通過API向後端程序發起請求?

我們用恆生雲的API,就要先申請恆生雲的調用權限,於是我申請了一個免費的試用

說明:恆生雲入口 https://hs.net , 如果你也想申請 可以註冊時用我的邀請碼 FP3GUX , 如果不申請也沒關係,我對已經請求的數據做了數據緩存,你運行我提供的程序包,即可獲得數據,學習用足夠了。

我們使用恆生雲的接口,還需要, access_token, token_type 這兩個參數,access_token, token_type相當於你的臨時身份ID,而這個臨時身份ID則需要使用恆生雲提供的key和secret, 進行獲取;以上規則在 https://www.hs.net/doc/100500_200550.html 裏有詳細的說明

我這裏提供通過key和secret獲取Authorization的代碼(key和secret兩個字段我留空了,換成自己免費申請的即可)。

const https = require('https');
// key 和 secret 要通過註冊恆生雲獲取
const key = "********";
const secret = "************";
// 獲得 access_token 文檔地址  https://www.hs.net/doc/100500_200550.html
const Authorization = "Basic " + Buffer.from(key+":"+secret).toString('base64');
console.log("==Authorization==>>", Authorization);
const postData = "grant_type=client_credentials";
const token_req = https.request({
    hostname: 'sandbox.hscloud.cn',
    path: '/oauth2/oauth2/token',
    method: "POST",
    headers : {
        'Authorization': Authorization,
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': postData.length
    },
},  (token_res)=>{
    token_res.on('data', (chunk) => {
        console.log(`BODY: ${chunk}`);
        const token_info = JSON.parse(chunk);
        const access_token = token_info["access_token"];
        const token_type = token_info["token_type"];
        console.log('token_info==>>', token_info);
        console.log('access_token==>>', access_token);
        console.log('token_type==>>', token_type);
    }
)})
token_req.write(postData);
token_req.end();
  • 有acccess_token, 和 token_type後,我們可以開始獲取交易日接口的信息了

圖中代碼

const https = require('https');

const key = "5ac2e1ee-789e-4d6b-a52d-f533b99d6a36";
const secret = "***********";

// 查看代碼前,請仔細閱讀文檔 文檔地址 https://www.hs.net/wiki/api/983_gildataastock_v1_commontable_tadingday.html
const Authorization = "Basic " + Buffer.from(key + ":" + secret).toString('base64')
console.log("==Authorization==>>", Authorization);
const postData = "grant_type=client_credentials";
let token_req = https.request({
    hostname: 'sandbox.hscloud.cn',
    path: '/oauth2/oauth2/token',
    method: "POST",
    headers: {
        'Authorization': Authorization,
        'Content-Type': 'application/x-www-form-urlencoded',
        'Content-Length': postData.length
    },
}, (token_res) => {
    token_res.on('data', (chunk) => {
        console.log(`BODY: ${chunk}`);
        const token_info = JSON.parse(chunk);
        const access_token = token_info["access_token"];
        const token_type = token_info["token_type"]
        // 開始請求
        //  secu_market=77 77代指美國納斯達克證券交易所 , start_data=2018-01-01 代指開始時間爲2018-01-01, end_date=2020-01-05代指結束時間爲2020-01-05
        const tadingday_post_data = `secu_market=77&start_date=2018-01-01&end_date=2020-01-05`;
        const tadingday_authorization = token_type + " " + access_token;
        let tadingday_res_body = "";
        const tadingday_req = https.request({
            method: "POST",
            hostname: 'sandbox.hscloud.cn',
            path: '/gildataastock/v1/commontable/tadingday',
            headers: {
                "Authorization": tadingday_authorization,
                'Content-Type': 'application/x-www-form-urlencoded',
                'Content-Length': tadingday_post_data.length
            }
        }, (tadingday_res) => {
            // 由於返回的數據量過於龐大, 服務器只能將數據分段返回給我們, 我們每次收到分段都會觸發data事件, 於是我們將每次返回的數據累加起來
            tadingday_res.on('data', (res_data) => {
                tadingday_res_body = tadingday_res_body + res_data;
            })
            // 當程序觸發 end事件時, 我們將已經獲得的數據打印到終端上
            tadingday_res.on('end', ()=>{
                console.log(tadingday_res_body);
            })
        })
        tadingday_req.write(tadingday_post_data);
        tadingday_req.end();
    });
})
token_req.write(postData);
token_req.end();

爲了能更好的展示這些數據,我們可以爲這些數據做個網頁

最終效果

我們寫代碼是爲了實現功能,而Node.js的優質工具包非常多,我們可以用很少的代碼,實現複雜的功能,爲了更好的使用和管理工具包,我們需要新建一個工程。

我們在終端輸入 node -v , 並回車,可以看到Node.js的版本;如果我們使用 npm -v 也可以看到 npm的版本

npm是隨同Node.js一起安裝的包管理工具, npm 全稱(node.js package manage), 我們使用 which node 和which npm 可以查看到, node和npm安裝在同一個目錄

創建工程的第一步是給工程起個名字,爲了避免出現亂七八糟的編碼轉換問題,工程和工程內的文件都使用英文字符命名

我們通過命令行創建一個名爲tadingday的文件夾,並以此文件夾作爲工程目錄,進行初始化

mkdir tadingday
cd tadingday
npm init -y

在開發過程中,我們需要用到兩個軟件包

nodemon:可以監聽文件內容變化,當文件內容變化時,自動重新運行程序,提升開發效率

express: 大名鼎鼎的Node.js服務器工具包,支持通過中間件,爲指定文件夾直接提供http服務,可以方便地解析前端請求參數,並返回數據。

安裝nodemon和express

npm install nodemon -D
npm install express

在項目文件夾中運行以上兩行代碼,即可順利安裝 nodemon和express

安裝成功後,我們項目文件夾會多出文件 package-lock.json, 以及文件夾 node_modules,原有 package.json文件的內容也會改變;

對於node_modules和package-lock.json, 我們知道它們存在的意義就好了,即使一不小心刪除了,也能通過npm install, 重新安裝回來。

而package.json則是非常重要的文件,我們需要理解其中的配置信息,並使用nodemon自定義一些指令

  • package.json重要字段解讀

爲了實現通過網頁直接輸入參數, 查詢恆生的交易日數據,我們需要使用express, 將我們以前的Node.js腳本改寫成,可以接受前端請求,返回相應數據的服務端程序;這個服務端程序不僅能將以前在終端打印的數據返回給瀏覽器,還需要將寫好的網頁返回給瀏覽器。

const https = require('https');
const express = require('express');

const app = express()

app.use(express.static('html'))
app.use(express.json()) // for parsing application/json
app.use(express.urlencoded({ extended: true })) // for parsing application/x-www-form-urlencoded


const port = 3000;

const key = "*******";
const secret = "*******";

// 文檔地址 https://www.hs.net/wiki/api/983_gildataastock_v1_commontable_tadingday.html
// 示例訪問鏈接 http://localhost:3000/gildataastock/v1/commontable/tadingday?end_date=2021-03-01&start_date=2021-01-01&secu_market=77

async function get_token() {
    const tadingday_authorization = await new Promise((resolve, reject) => {
        const Authorization = "Basic " + Buffer.from(key + ":" + secret).toString('base64')
        console.log("==Authorization==>>", Authorization);
        const postData = "grant_type=client_credentials";
        let token_res_data = "";
        let token_req = https.request({
            hostname: 'sandbox.hscloud.cn',
            path: '/oauth2/oauth2/token',
            method: "POST",
            headers: {
                'Authorization': Authorization,
                'Content-Type': 'application/x-www-form-urlencoded',
                'Content-Length': postData.length
            },
        }, (token_res) => {
            token_res.on('data', (chunk) => {
                token_res_data = token_res_data + chunk;
            });
            token_res.on('end', () => {

                console.log(`BODY: ${token_res_data}`);
                const token_info = JSON.parse(token_res_data);
                const access_token = token_info["access_token"];
                const token_type = token_info["token_type"]
                const tadingday_authorization = token_type + " " + access_token;
                console.log('==tadingday_authorization==>>', tadingday_authorization);
                resolve(tadingday_authorization);
            })
        })
        token_req.write(postData);
        token_req.end();
    })

    return tadingday_authorization;
}

app.get('/gildataastock/v1/commontable/tadingday', async (req, res) => {

    const tadingday_authorization = await get_token();
    console.log('req==>>', req);
    const secu_market = req.query.secu_market;
    const start_date = req.query.start_date;
    const end_date = req.query.end_date;


    // 開始請求
    const tadingday_post_data = `secu_market=${secu_market}&start_date=${start_date}&end_date=${end_date}`;
    let tadingday_res_body = "";
    const tadingday_req = https.request({
        method: "POST",
        hostname: 'sandbox.hscloud.cn',
        path: '/gildataastock/v1/commontable/tadingday',
        headers: {
            "Authorization": tadingday_authorization,
            'Content-Type': 'application/x-www-form-urlencoded',
            'Content-Length': tadingday_post_data.length
        }
    }, (tadingday_res) => {

        tadingday_res.on('data', (res_data) => {
            tadingday_res_body = tadingday_res_body + res_data;
        })

        tadingday_res.on('end', () => {
            console.log(`BODY: ${tadingday_res_body}`);
            tadingday_res_body = JSON.parse(tadingday_res_body);
            // console.log('=res_data==>>', tadingday_res_body)
            res.send(tadingday_res_body)
        })
    })
    console.log('tadingday_post_data===>>', tadingday_post_data)
    tadingday_req.write(tadingday_post_data);
    tadingday_req.end();
})

app.listen(port, () => {
    console.log(`Example app listening at http://localhost:${port}`)
})

運行這個服務端程序後

我們可以通過訪問

http://localhost:3000/gildataastock/v1/commontable/tadingday?end_date=2021-03-01&start_date=2021-01-01&secu_market=77

直接從瀏覽器獲取數據

這段代碼裏使用了express內置的static中間件,直接將html文件夾中的網頁內容,作爲服務端文件返回

我們訪問 http://localhost:3000/tadingday/index.html 也就能自動獲取tadingday文件夾中的index.html文件

index.html的網頁內容如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="./static/bootstrap.min.css" rel="stylesheet">
    <script src="./static/jquery-3.6.0.min.js"></script>

    <title>交易日批量查詢</title>
</head>
<body>

    <style>

        .content_info{

            display: inline-block;

            width: 100px;

            margin-bottom: 20px;
            color: #FFFFFF;
            text-align: center;
        }

        #content{
            display: flex;
            justify-content: space-between;
            flex-wrap: wrap
        }


    </style>

    <script>


        let params = {
            start_date: "2021-06-01",
            end_date : "2021-09-01",
            secu_market : "71"
        }




        function change_start_date(start_date){

            console.log('start_date:', start_date);

            params.start_date = start_date;


        }


        function change_end_date(end_date){

            console.log('end_date:', end_date);

            params.end_date = end_date;

        }


        function change_secu_market(){

            let secu_market_select_dom = document.getElementById("secu_market_select");

            let selected_option_info = secu_market_select_dom.options[secu_market_select_dom.selectedIndex]

            params.secu_market = selected_option_info.value

        }

        // 檢查參數

        function check(start_date, end_date, secu_market) {

            let check_pass = true;

            if(start_date.length === 0){

                check_pass = false;
                alert("請選擇開始時間!");

            }


            if(check_pass && end_date.length === 0) {
                check_pass = false;
                alert("請選擇結束時間!");

            }

            if(check_pass && start_date >= end_date) {

                alert("開始時間不得小於或等於結束時間,請重新選擇!");
            }

            if(secu_market.length === 0) {

                alert("請選擇類型!")
            }


            return check_pass

        }

        // 提交請求,獲取數據
        function submit(){

            const check_pass = check(params.start_date, params.end_date, params.secu_market);


            if(check_pass === true){

                $.ajax({
                    url: `http://localhost:3000/gildataastock/v1/commontable/tadingday?start_date=${params.start_date}&end_date=${params.end_date}&secu_market=${params.secu_market}`,
                    type: "get",
                    success: (data, textStatus, jqXHR)=>{

                        console.log("data==>>", data);


                        let content_info = "";
                        
                        data["data"].map((value)=>{
                            const if_trading_day =  value["if_trading_day"];
                            const trading_date =  value["trading_date"];

                            const background_color = if_trading_day === "是" ? "#8DC43E": "#F16421";


                            content_info = content_info + `<div class="content_info" style='background-color: ${background_color};'>${trading_date}</div>`



                        })



                        $('#content').html(content_info);


                    }

                })

            }
            




        }

    </script>

    <div style="text-align: center; font-size: 30px;padding: 20px">交易日批量查詢</div>

    <div style="display: flex;justify-content: space-between; margin: 0 20px;">
    

    <div>
        <span>開始日期</span>
        <input onchange="change_start_date(value)" type='date' value="2021-06-01"/>
    </div> 
    
    
    
    <div>
        <span>結束日期</span>
        <input onchange="change_end_date(value)" type='date' value="2021-09-01"/>
    </div> 
    
    
    <div>
        <span>選擇類型</span> 
        <select class="form-select" default id="secu_market_select" onchange="change_secu_market()">
        <option value="71" selected>櫃檯交易市場</option>
        <option value="72">香港聯交所</option>
        <option value="77">美國納斯達克證券交易所</option>
        <option value="83">滬深證券交易所</option>
        <option value="89">銀行間債券市場</option>
      </select> 
    </div>

    <button  class="btn btn-success" onclick="submit()">查詢</button>

</div>

<div id="content"></div>
    
</body>
</html>

這段html裏還使用了 jQuery 和BootStrap這兩個經典前端包,內容放在static文件夾中

static 可以從github下載,地址 https://github.com/zhaoolee/it/tree/main/src/Class001/tadingday/html/tadingday/static

新建一個SQLite本地數據庫,將請求數據保存到數據庫中

首先,我們需要安裝一個Node.js操作sqlite的依賴包 better-sqlite3

npm i better-sqlite3
  • 在項目根目錄新建一個文件夾db
  • 通過better-sqlite3新建數據庫並創建數據表

    // 初始化數據庫
    const db = require('better-sqlite3')(path.join(__dirname, "..", "data", "tadingday.sqlite"));
    // 新建數據表
    //  secu_market: 證券市場  if_trading_day:是否交易日 if_week_end:是否週末 if_month_end:是否月末  if_quarter_end:是否季末   if_year_end:是否年末 trading_date:交易日期
    db.exec(`
        CREATE TABLE IF NOT EXISTS tadingday_info (
            secu_market VARCHAR(50),
            if_trading_day VARCHAR(10),
            if_week_end VARCHAR(10), 
            if_month_end VARCHAR(10), 
            if_quarter_end VARCHAR(10),  
            if_year_end VARCHAR(10), 
            trading_date VARCHAR(16), 
            request_secu_market VARCHAR(16),
            PRIMARY KEY(request_secu_market, trading_date)
        );
    `);
    

安裝一個sqlite數據查看插件Sqlite Viewer

安裝插件Sqlite Viewer後可以查看數據庫,數據表

在數據庫中,一行數據被稱作一條記錄, 每一列的列名被稱作字段

使用Sql往數據庫插入記錄的語法

INSERT INTO table_name (字段名1,字段名2,字段名3,...) VALUES (字段名1對應的值,字段名2對應的值,字段名3對應的值,...);

代碼思路:當請求獲得數據時,調用sava_data函數, 將請求獲得的數據,存儲到本地sqlite數據庫中

// 往本地數據庫插入數據
const insert_tadingday_info = db.prepare(`INSERT INTO tadingday_info (
    secu_market,
    if_trading_day,
    if_week_end, 
    if_month_end, 
    if_quarter_end,  
    if_year_end, 
    trading_date,
    request_secu_market
) values (
    @secu_market,
    @if_trading_day,
    @if_week_end, 
    @if_month_end, 
    @if_quarter_end,  
    @if_year_end, 
    @trading_date,
    @request_secu_market
);`);


// 返回給前端後,存儲到數據庫

tadingday_res.on('end', () => {
    console.log(`BODY: ${tadingday_res_body}`);
    tadingday_res_body = JSON.parse(tadingday_res_body);
    res.send(tadingday_res_body)

    // 存入數據庫

    tadingday_res_body["data"].map((value) => {
        value['request_secu_market'] = secu_market
        sava_data(value)
    })

})
            
// 使用sqlite數據庫存儲請求來的數據

function sava_data(tadingday_info_atom) {
    const { secu_market, if_trading_day, if_week_end, if_month_end, if_quarter_end, if_year_end, trading_date, request_secu_market } = tadingday_info_atom;
    try {        
        insert_tadingday_info.run(
            {
                "secu_market": secu_market, 
                "if_trading_day": if_trading_day, 
                "if_week_end": if_week_end, 
                "if_month_end": if_month_end, 
                "if_quarter_end": if_quarter_end, 
                "if_year_end": if_year_end, 
                "trading_date": trading_date, 
                "request_secu_market": request_secu_market
            }
        );
    } catch (e) {
        // console.log(e);
    }

}

在數據源失效時,查詢本地數據庫獲取數據

使用Sql往從數據庫獲取記錄的語法


SELECT  字段名(如果選擇所有字段則使用星號\*)  FROM 表名 WHERE 條件;

SQL代碼思路:

選擇交易日期trading_date字段 小於結束時間end_date 並且 大於開始時間start_date 並且 證券市場代號request_secu_market 等於特定的值

select * from tadingday_info 
    WHERE 
    trading_date >= @start_date AND 
    trading_date <= @end_date AND 
    request_secu_market = @request_secu_market;`

完整代碼

// 從本地數據庫取數據
const select_tadingday_info = db.prepare(`select * from tadingday_info 
    WHERE 
    trading_date >= @start_date AND 
    trading_date <= @end_date AND 
    request_secu_market = @request_secu_market;`
);

// 從本地數據庫獲取數據
function select_data(value) {
    const { start_date, end_date, request_secu_market } = value;

    console.log("==從本地數據庫取數據==")

    try {

        const result_data = select_tadingday_info.all(
            {
                "start_date": start_date, 
                "end_date": end_date, 
                "request_secu_market": request_secu_market
            }
        );
        console.log('=result_data=>>', result_data);
        return result_data
    } catch (e) {
        // console.log(e);
    }

}

運行完整工程代碼

運行方法

git clone https://github.com/zhaoolee/it.git --depth=1
cd it/src/Class001/tadingday
npm install
npm run dev004

啓動項目的小工具包

啓動項目使用了4個小工具包

nodemon的作用是監聽特定文件夾,文件內容的變化,當文件產生變化時(保存文件可觸發),重新啓動項目,讓剛剛編寫的代碼生效。

opener的作用是在瀏覽器啓動新標籤頁,打開特定url的網頁

concurrently 的作用是同時運行多個指令,我們運行004-tadingday-server-and-sqlite.js 文件時,會產生阻塞;而concurrently可以讓我們同時運行004-tadingday-server-and-sqlite.js文件和 opener打開特定頁面的指令。

wait-on 是一個判斷條件的包,我們啓用後臺服務程序會監聽3000端口;但後臺服務啓動需要一些時間,如果3000端口還未被綁定時,瀏覽器就已經開始請求,那就會出現請求失敗,而wait-on包可以幫我們做一個判斷,當3000端口被使用的時候,再使用瀏覽器打開特定頁面,這樣就不會出現打開瀏覽器白屏的情況

  "scripts": {
"dev004": "concurrently  'nodemon ./src/004-tadingday-server-and-sqlite.js --watch ./' 'wait-on tcp:3000 && opener http://localhost:3000/tadingday'"
  }

package.json中scripts的語法小技巧:

scripts 的指令可以非常靈活的自定義,都是鍵值對的形式,鍵爲dev004, 後面的一長串就是值, 這個值需要使用整體引號包裹,如果內部出現子指令,則需要通過單引號包裹。

&& 符號代表了先後關係,前面一個指令執行完成了,後面的指令纔會執行。

本文永久更新地址(歡迎來讀留言,寫評論):

https://www.v2fy.com/p/2021-10-27-node_js-1635325734000

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章