很前面的文章「Console Mode 還能怎麼玩,開發與 Debug 技巧」,有講到說我們推薦用這種 Action Function 的方式來整理程式,並回傳給 Bottender 去執行:
const random = require('random-item');
async function SendJoke(context) {
await context.sendText(
random([
'加油站最怕什麼樣的員工?油腔滑調的員工',
'有一天,西瓜、榴槤、奇異果一起出去玩,結果榴槤不見了。因為榴槤忘返',
'海記憶體知己,天涯若比鄰',
])
);
}
module.exports = async function App(context) {
return SendJoke;
};
但只是這樣做,可能有些人已經發現了一個問題,如果我想要擴充這個 Action 或增加它的彈性,似乎沒辦法做到,因為這個 Action 就寫好在那裡,沒有提供傳參數的管道。
因此,今天要來利用傳參數的方式來看看這對模組化好會有什麼好處。
(注意:今天請務必使用最新版本的 bottender,較舊的版本可能會沒有這個功能)
假想一下,當今天我想要開發一個講笑話的 Action,讓別人直接這樣使用:
const SendJoke = require('./SendJoke');
他的 SendJoke.js
應該就是這樣寫:
// SendJoke.js
const random = require('random-item');
module.exports = async function SendJoke(context) {
await context.sendText(
random([
'加油站最怕什麼樣的員工?油腔滑調的員工',
'有一天,西瓜、榴槤、奇異果一起出去玩,結果榴槤不見了。因為榴槤忘返',
'海記憶體知己,天涯若比鄰',
])
);
}
乍看之下也是可以,但某一天有人提出問題了:「我可不可以加一些自己的笑話進去?」。這樣就麻煩了,他的笑話可能不好笑,我沒有想要把它納入我的模組裡面啊...。
想了想,你可能會只想讓他的笑話出現在他的程式裡,因此我們需要傳參數的方法。
先來看看我們要怎麼改寫:
// SendJoke.js
const random = require('random-item');
module.exports = async function SendJoke(context, props) {
const extraJokes = props.jokes || [];
await context.sendText(
random([
'加油站最怕什麼樣的員工?油腔滑調的員工',
'有一天,西瓜、榴槤、奇異果一起出去玩,結果榴槤不見了。因為榴槤忘返',
'海記憶體知己,天涯若比鄰',
...extraJokes,
])
);
}
這邊大家會注意到第二個參數 props
,我們讓它接收了 jokes
的陣列,並把它添加到笑話裡。
接下來要看一下這樣的 Action 要如何去使用,因為想不到什麼好笑話,所以決定借用一下碼天狗的笑話:
const { withProps } = require('bottender');
const SendJoke = require('./SendJoke');
module.exports = async function App(context) {
return withProps(SendJoke, {
jokes: [
'軟體設計最困難的部分... 是阻擋新功能的引入',
'工作進度上越快落後,你就會有越充足的時間趕上',
'評估一件事情要比去理解你評估了什麼容易',
'本系統上次更新時間:NaN/NaN/NaN',
'我喜歡在填表單的時候加一些 � 和 ’,好讓那些工程師懷疑系統有 bug',
'我們公司有一個 Ting 可以支援這個專案,我們公司有 Michael service 提供完整服務',
],
});
};
我們利用 withProps
這個 Function 來讓 Action 附帶指定的 props
。執行起來是這樣:
props
是一個 freeze 過的物件,不可修改。接下來不久後可能會導入 React 的 PropTypes,並視情況看看是否只在開發環境 freeze props
。
在經過今天這個主題後,大家應該有漸漸發現要怎樣去寫會比較好維護、比較好預測了,不妨在你的 Bottender App 裡面馬上試試看吧。