用 node.js 的 request library 串接 API


本篇會介紹如何用 request 這套 library 在 node.js上串接 API,實作的部份也是程式導師計畫第四週的內容及作業:

基礎知識

因為我們要使用 npm 上 request 這套 library,首先第一步是要確認有安裝 node.js ,並初始化 npm,npm 簡易教學可以參考這篇,之後就可以用 npm install request 來安裝這套 library 啦。

完成安裝後,我們先來查找 request 的文件來看看怎麼發最基本的 GET request

結果文件的第一行就寫得很清楚了 XDD

  1. 宣告一個變數來引入 request 之後
  2. request 的第一個參數是要串接 API 的 url,第二個參數是箭頭函式,可以取得 response, error, statusCode 和 body 等資料都放在這裡。
  3. 讓我們加入 try... catch 來處理成功和失敗的狀況吧,於是 test_api.js 這支程式碼會像這樣:
const request = require('request');

request.post(
  'https://example.com,
  (error, response, body) => {
    let data;
    try {
      data = JSON.parse(body);
      //如果成功就把 body 轉成 JSON 物件
    } catch (err) {
      console.log('API抓取錯誤', error);
      return;
      // 如果失敗就顯示 API 抓取錯誤並跳出
    }
    console.log(data);
    // 印出接收到的 data
  },
);

在使用終端機輸入 node test_api.js 執行程式,就可以得到回傳的 response data 了~

寫作業啦

有了初步的串接 API 的知識之後,我們來做做看程式導師計畫第四週的作業吧~

API 文件

Base URL: https://lidemy-book-store.herokuapp.com

說明 Method path 參數 範例
獲取所有書籍 GET /books _limit:限制回傳資料數量 /books?_limit=5
獲取單一書籍 GET /books/:id /books/10
新增書籍 POST /books name: 書名
刪除書籍 DELETE /books/:id
更改書籍資訊 PATCH /books/:id name: 書名

hw1:來自秋秋鞋的任務

有一天,住你隔壁的鄰居秋秋鞋跑來按門鈴,說有事想要找你討論,他最近在做一個知識型的 YouTube 頻道,可是快要沒有靈感了。

這時,他想到一個好主意!他只要能夠看到書店提供的書籍相關資訊,就可以從中汲取靈感,之後就可以發想相關題材,頻道就不會一直不更新了。

身為秋秋鞋的好朋友,這個重責大任當然就交給你了!

請閱讀開頭給的 API 文件並串接,用 node.js 寫出一個程式,執行後會在 console 列出前十本書籍的 id 以及書名。

範例:
node hw1.js

1 克雷的橋
2 當我想你時,全世界都救不了我
3 我殺的人與殺我的人
....

所以要獲取所有書籍,可以參考 API 文件使用 GET 方法,對應的 path 就是 /books
我們就使用剛才學會的 request 來串串看吧

const request = require('request');

request.get(
  'https://lidemy-book-store.herokuapp.com/books?_limit=10',
  (error, response, body) => {
    let data;
    try {
      data = JSON.parse(body);
    } catch (err) {
      console.log('API抓取錯誤', error);
      return;
    }
      console.log(data)
    }
  },
);

拿到之後,直接 node hw1.js 把資料印出來看看有沒有成功,結果獲得一個陣列...

[
  { id: 1, name: '克雷的橋' },
  { id: 2, name: '當我想你時,全世界都救不了我' },
  { id: 3, name: '我殺的人與殺我的人' },
  { id: 4, name: '念念時光真味' },
  { id: 5, name: '蜂蜜花火【致年少時光‧限量插畫設計書衣典藏版】' },
  { id: 6, name: '苦雨之地' },
  { id: 7, name: '你已走遠,我還在練習道別' },
  { id: 8, name: '想把餘生的溫柔都給你' },
  { id: 9, name: '你是我最熟悉的陌生人' },
  { id: 10, name: '偷書賊(25萬本紀念版本)' }
]

現在要思考怎麼輸出成作業要求的格式,有 10 筆資料要輸出,哦哦,可以用迴圈印出每筆資料的 id 和書名
第 i 筆資料就是 data[i],它的 id 就是 data[i].id,而書名就是 data[i].name(如果不熟可以回去複習 JavaScript 物件和陣列的概念),所以我們就可以這樣寫:

const request = require('request');

request.get(
  'https://lidemy-book-store.herokuapp.com/books?_limit=10',
  (error, response, body) => {
    let data;
    try {
      data = JSON.parse(body);
    } catch (err) {
      console.log('API抓取錯誤', error);
      return;
    }
    for (let i = 0; i < data.length; i += 1) {
      console.log(`${data[i].id} ${data[i].name}`);
    }
  },
);

就可以拿到結果啦

λ node test.js
1 克雷的橋
2 當我想你時,全世界都救不了我
3 我殺的人與殺我的人
4 念念時光真味
5 蜂蜜花火【致年少時光‧限量插畫設計書衣典藏版】
6 苦雨之地
7 你已走遠,我還在練習道別
8 想把餘生的溫柔都給你
9 你是我最熟悉的陌生人
10 偷書賊(25萬本紀念版本)

hw2:最後的考驗

原本以為上次就已經是最後一次幫忙,沒想到秋秋鞋還是又跑來找你了。他說他想要更多功能,他想把這整個書籍資料庫當作自己的來用,必須能夠顯示前 20 本書的資料、刪除、新增以及修改書本,這樣他就可以管理自己的書籍了。

(跟 hw1 不同,之前是 10 本,這次要顯示 20 本)

雖然你很想問他說為什麼不用 Excel 就好,但你問不出口,再加上你最近剛學程式需要練習的機會,於是你就答應了。

請閱讀開頭給的 API 文件並串接,用 node.js 寫出一個程式並接受參數,輸出相對應的結果,範例如下:

node hw2.js list // 印出前二十本書的 id 與書名
node hw2.js read 1 // 輸出 id 為 1 的書籍
node hw2.js delete 1 // 刪除 id 為 1 的書籍
node hw2.js create "I love coding" // 新增一本名為 I love coding 的書
node hw2.js update 1 "new name" // 更新 id 為 1 的書名為 new name

作業二的精華在於要怎麼在終端機輸入不同命令以呼叫不同的 API 功能,可以利用 process.argv 這個陣列拿到對應的參數:
把 process.argv 這個陣列利用 console.log 印出來之後有人驚人的發現
以 node test.js 這行終端機指令來說,process.argv[0] 就是 node,prcess.argv[1] 就是 test.js,所以也就是說,我們可以在自訂義之後的參數,然後利用 if 判斷式來判斷 prcess.argv[2] 是 list, read, delete, create 還是 update,來做不同的 path 串接,如此一來....

可以先把執行的這些參數的位置都宣告成變數

/* eslint-disable no-unused-vars */
const request = require('request');

const action = process.argv[2];
const parameter = process.argv[3];
const parameterTwo = process.argv[4];
const APIUrl = 'https://lidemy-book-store.herokuapp.com';

當執行參數是什麼,我們就執行對應的什麼函式以呼叫 API

switch (action) {
  case 'list':
    listBook();
    break;
  case 'read':
    readBook(parameter);
    break;
  case 'delete':
    deleteBook(parameter);
    break;
  case 'create':
    createBook(parameter);
    break;
  case 'update':
    updateBook(parameter, parameterTwo);
    break;
  case 'manual':
    manual();
    break;
  default:
    console.log('可執行的指令: list, read, delete, create, update, manual');
    console.log('執行指令 node hw2.js manual 可查看各指令用法');
}

接下來就只是把不同的 call API 方法包在一個個函式裡面等待我們執行的時候去呼叫啦

function listBook() {
  request.get(
    `${APIUrl}/books?_limit=20`,
    (error, response, body) => {
      let data;
      try {
        data = JSON.parse(body);
      } catch (err) {
        console.log('API抓取錯誤', error);
        return;
      }
      for (let i = 0; i < data.length; i += 1) {
        console.log(`${data[i].id} ${data[i].name}`);
      }
    },
  );
}

function readBook(id) {
  request.get(
    `${APIUrl}/books/${id}`,
    (error, response, body) => {
      let data;
      try {
        data = JSON.parse(body);
      } catch (err) {
        console.log('API抓取錯誤', error);
        return;
      }
      console.log(`${data.id} ${data.name}`);
    },
  );
}

function deleteBook(id) {
  request.delete(
    `${APIUrl}/books/${id}`,
    (error, response, body) => {
      try {
        console.log('刪掉啦');
      } catch (err) {
        console.log('沒刪到', error);
      }
    },
  );
}

function createBook(name) {
  request.post({
    url: `${APIUrl}/books`,
    form: {
      name,
    },
  }, (error, response, body) => {
    try {
      console.log(`《${name}》新增成功`);
    } catch (err) {
      console.log('新增失敗', error);
    }
  });
}

function updateBook(id, name) {
  request.patch({
    url: `${APIUrl}/books/${id}`,
    form: {
      name,
    },
  }, (error, response, body) => {
    try {
      console.log(`${id} 已修改為 ${name}`);
    } catch (err) {
      console.log('修改失敗', error);
    }
  });
}

function manual() {
  console.log('list (列出前 20 本書的 id 及書名)');
  console.log('read x (輸出id為x的書)');
  console.log('delete x (刪除 id 為 x 的書)');
  console.log('create name (新增一本名為 name 的書)');
  console.log('update x n(更新 id 為 x 的書為 n)');
}

雖然實作上有點麻煩,但只要掌握 process.argv 這個陣列的使用應該就比較容易了吧 ^__^







你可能感興趣的文章

Android 不負責任系列 - Jetpack 組件、MVVM 架構,簡稱 AAC、整潔架構(Clean Architecture) 的領域層(Domain Layer) UseCase 介紹

Android 不負責任系列 - Jetpack 組件、MVVM 架構,簡稱 AAC、整潔架構(Clean Architecture) 的領域層(Domain Layer) UseCase 介紹

[21] 強制轉型 - ToNumber、ToPrimitive、StringNumericLiteral、NonDecimalIntegerLiteral

[21] 強制轉型 - ToNumber、ToPrimitive、StringNumericLiteral、NonDecimalIntegerLiteral

每日心得筆記 2020-06-16(二)

每日心得筆記 2020-06-16(二)






留言討論