如果不用 Node.js 寫業務

蘇洋發表於2018-09-12

本站使用「署名 4.0 國際 (CC BY 4.0)」許可協議,歡迎轉載、或重新修改使用,但需要註明來源。 署名 4.0 國際 (CC BY 4.0)

本文作者: 蘇洋

建立時間: 2018年08月31日 統計字數: 4273字 閱讀時間: 9分鐘閱讀 本文連結: soulteary.com/2018/08/31/…


如果不用 Node.js 寫業務

最近整理部落格,發現很久沒有介紹語言相關的小用法了,正巧休息的時候把程式碼倉庫歸置了一遍,用幾個簡短的例子,聊聊 Node.js 除了寫業務指令碼、做構建執行時,它還能做些什麼有趣的事情吧。

持續整合中的粘合劑

在做持續整合中,偶爾會遇到需要解析 API 結果,或者讀取檔案,獲取檔案指定資料的需求,當使用常規的 shell 難以完成需求的時候,相比較 Python 來說使用 Node 做為粘合劑來獲取資料不失為一個好的方案,因為寫出的程式碼將會更簡單明瞭。

示例

比如你希望獲取到某些 API 中的特殊欄位,然後再次進行引數拼裝,請求其他的 API ,完成某種程度的完全自動化操作。

使用 Node.jsfs.readFileSync 方法讀取 /dev/stdin 即可,比如:

curl SOME_API_WITH_ARGS | node -e 'console.log(JSON.parse(require("fs").readFileSync("/dev/stdin").toString()).data);'
複製程式碼

當然,你也可以把這個指令碼儲存為檔案,然後進行呼叫,結果是一樣的。

const fs = require("fs");console.log(JSON.parse(fs.readFileSync("/dev/stdin").toString()).iid);
複製程式碼

如果將上面的程式碼儲存為 pipe.js,那麼接下來執行下面的程式碼,將會得到相同的結果。

echo data | node pipe.js
複製程式碼

輔助進行資料清理

一提到資料清理,大家會不自覺地想到 SQLPythonR,但是有的時候,並不需要進行大量編碼,使用系統內建的 Shell 配合 Node.js 在實現和效率上都會變的更快。

示例

程式構建完畢,想看看到底有多少內容是冗餘的,那麼便要進行檔案去重操作。通常我們並不能夠簡單依賴檔名稱進行去重,這個時候就要使用檔案內容簽名來做了。

使用靜態編譯的 shell 工具可以快速計算出檔案的簽名:

find . | xargs -I {} shasum -a 256 {}

shasum: ./dist: 
shasum: ./dist/some: 
b0a635b4d6be1a6f14f25c64e3ff6fa2ccacc4e55be93d6f542184a386f748c8  ./dist/some/aea0d6c054cf3fadf5bb.js
9498cb1451fc6d02612610f109ebb29dc94957e2a2741b701443182573837bfc  ./dist/some/
複製程式碼

這個輸出結果會有許多看起來無意義的行,這個時候配合上一小節的方法,將輸出結果當引數傳遞給 Node.js 程式只需要幾行程式碼就能將檔案分析完畢。

const fs = require('fs');

const shasumList = fs.readFileSync('/dev/stdin').toString().split('\n').filter(l => l).filter(l => l.match(/^\w{64}\s+\S+$/));

let reduceResult = {};

shasumList.map(item => {
  const [shasum, name] = item.match(/(\w+)\s+(\S+)/);
  return {shasum, name};
}).forEach(item => {
  reduceResult[item.shasum] = reduceResult[item.shasum] || [];
  reduceResult[item.shasum].push(item.name);
});

console.log(reduceResult);
複製程式碼

當然,如果你願意的話,寫個簡單的目錄掃描,然後使用 Node.jscrypto 模組直接計算簽名也是可以的。

const fs = require('fs');
const crypto = require('crypto');
const secret = '';

const hash = crypto.createHmac('sha256', secret).update(fs.readFileSync(`${item.name}-${item.id}.html`).toString()).digest('hex');
複製程式碼

柯里化外部操作

標題看起來是不是很熟悉,一般提到柯里化,我們會想到使用更少的引數去封裝後面的高階函式。使用 Node.js 可以提供類似的功能,只不過這裡的 curry 發生的級別不是程式碼級別。

示例

比如我找到了一些零幾年古老的程式碼片段,它們原本不存在於 CVS 版本控制系統中,倘若直接新增,提交時間就是當下提交的時刻。但是這些檔案本身提供了建立時間,可以作為原始資訊一併入庫。

這個時候,使用 git commit --date 可以修改提交時間戳,但是實際使用起來卻很麻煩,因為它要保持一個特定的格式:ddd, DD MMM YYYY HH:MM:SS +8000

如果這裡有一個小指令碼可以將輸入的時間自動轉換成這個格式,那麼處理這些檔案就方便多了。

#!/usr/bin/env node

var moment = require('moment');

var argvs = process.argv.slice(2);

console.log('input:', argvs[0]);

if (!argvs.length) {
  console.log('useage: tool timestamp');
  process.exit(1);
}

console.log('output:\n');

if (argvs.length === 2) {
  console.log('git add .');
  console.log('gc -m "' + argvs[0] + '" --date="' + moment(new Date(argvs[1])).format('ddd, DD MMM YYYY HH:MM:SS +8000') + '"');
  console.log('git push');
} else {
  console.log('gc --amend -m "' + moment(new Date(argvs[0])).format('ddd, DD MMM YYYY HH:MM:SS +8000') + '" --date="' + moment(new Date(argvs[0])).format('ddd, DD MMM YYYY HH:MM:SS +8000') + '"');
  console.log('git push -f');
}
複製程式碼

當然,如果你將這個指令碼儲存到一個全域性可以找到的路徑,然後賦予執行許可權,還可以在指令碼中新增 exec 操作,讓程式碼能夠自動提交。

輔助檔案管理

除了作為資料管理的工具外,Node.js 提供的檔案操作模組,還能輔助我們進行檔案整理。

示例

在購買了 XX音樂包XX會員 之後,發現歌曲音質確實好了不少,但是音質的代價是不得不將大量檔案快取在移動裝置中,即使用著 256G 的移動裝置,也不堪長年累月的快取之重。於是我把裝置中的音樂匯出、也從其他地方下載了一些音樂,計劃將它們同一歸置到一臺專門的裝置中進行管理存放,但是幾千首隨機生成的檔名十分不利於歸檔,好在多數檔案中包含了音樂資訊 ID3,配合解析軟體包,讓程式自動將他們重新命名和程式存放吧。

const {readdirSync, renameSync, statSync, unlinkSync, existsSync, mkdirSync} = require('fs');
const {join} = require('path');
const {inspect} = require('util');
const {parseFile} = require('music-metadata');

const {rootDir} = require('./config');

const files = readdirSync(rootDir).
    filter((file) => file.endsWith('.m4a') || file.endsWith('.flac') || file.endsWith('.mp3'));

files.forEach((file) => {
  const fullPath = join(rootDir, file);

  parseFile(fullPath, {native: true}).then((metadata) => {
    const name = `${metadata.common.title.trim()} - ${metadata.common.artist.trim()}.${file.split('.').pop()}`;

    if (name !== file) {
      renameSync(fullPath, join(rootDir, name));
    }

  }).catch((err) => {
    if (statSync(fullPath).size < 10) {
      unlinkSync(fullPath);
    } else {
      console.log('parse error', statSync(fullPath).size);
      console.error(err.message);
    }
  });
});

readdirSync(rootDir).filter((file) => {
  if (file.includes(' - ')) {
    let lastPart = file.split(' - ')[1];
    const name = lastPart.replace(/\..+/, '');

    const target = join(rootDir, name);

    if (!existsSync(target)) mkdirSync(target);
    renameSync(join(rootDir, file), join(target, file));
  }
});
複製程式碼

其他

像上面使用 Node 只寫十幾行程式碼就能完成任務的事情還有很多,比如之前:

  • 給公司做過智慧裝置閘道器,監聽公司大門是否忘記關閉,使用企業微信介面快速通知負責人。
  • 編寫簡單 UDP 指令碼控制家裡的各種裝置自動休眠和喚醒。
  • 一些遊戲存檔修改器 XD
  • 快速爬取任何瀏覽過的網站。

我現在有一個小小的折騰群,裡面聚集了一些喜歡折騰的小夥伴。

在不發廣告的情況下,我們在裡面會一起聊聊軟體、HomeLab、程式設計上的一些問題,也會在群裡不定期的分享一些技術沙龍的資料。

喜歡折騰的小夥伴歡迎掃碼新增好友。(請註明來源和目的,否則不會通過稽核) 關於折騰群入群的那些事

關於折騰群入群的那些事

相關文章