&&
與 ||
為 ECMAScript 很具代表性的 Operator,事實上 ,
與 &&
與 ||
非常類似,尤其在 Promise Chain 中非常實用。
Version
ECMAScript 5
Synchronous
let y = 1
let x = y
x = x + 1
let z = x + y
z // ?
重點在 z
必須先執行 x = x + 1
,然後再 x + y
,一共需要兩行。
let x = y = 1
let z = (x++, x + y)
z // ?
可將 x++
與 x + y
使用 comma operator 合併成一行。
Asynchronous
let x = Promise.resolve(1)
let y = Promise.resolve(1)
let x_ = await x + 1
let z = x_ + await y
await z // ?
若 x
與 y
為 Promise,則要將原本 synchronous 都加上 await
。
let x = Promise.resolve(1)
let y = Promise.resolve(1)
let z = x
.then(x => x + 1)
.then(async x => x + await y)
await z // ?
也可改用 Promise Chain,由於第二個 .then()
又相依 Promise,因此在 callback 內直接使用 Async Await 較為精簡。
let x = Promise.resolve(1)
let y = Promise.resolve(1)
let z = x
.then(async x => (x++, x + await y))
await z // ?
可使用 comma operator 將兩行合併成一行。
Promise Chain
Get Book
按下會同時顯示 FP in JavaScript
與 FP
。
<template>
<div>
<button @click="onClick">Get Book</button>
{{ title }} / {{ category }}
</div>
</template>
<script>
import axios from 'axios'
let fetchBook = x => axios.get(`http://localhost:3000/books/${x}`)
.then(x => x.data)
let fetchCategory = x => axios.get(`http://localhost:3000/categories/${x}`)
.then(x => x.data)
let onClick = function() {
fetchBook(1)
.then(x => (this.title = x.title, x))
.then(x => fetchCategory(x.categoryId))
.then(x => this.category = x.category)
.catch(console.error)
}
export default {
name:'App',
data:() => ({
title: '',
category: '',
}),
methods:{
onClick
}
}
</script>
實務上 comma operator 真正有用是在 Promise Chain 處理上。
18 行
fetchBook(1)
.then(x => (this.title = x.title, x))
.then(x => fetchCategory(x.categoryId))
.then(x => this.category = x.category)
.catch(console.log)
第一個 .then()
的 x
為 book
,它有兩個任務:
- 寫入
title
side effect - 回傳
x
供下一個 API function 使用
傳統會寫成兩行,但透過 comma operator 只要一行即可。
Function Pipeline
<template>
<div>
<button @click="onClick">Get Book</button>
{{ title }} / {{ category }}
</div>
</template>
<script>
import { pipe, andThen as then, otherwise } from 'ramda'
import axios from 'axios'
let fetchBook = x => axios.get(`http://localhost:3000/books/${x}`)
.then(x => x.data)
let fetchCategory = x => axios.get(`http://localhost:3000/categories/${x}`)
.then(x => x.data)
let onClick = function() {
pipe(
fetchBook,
then(x => (this.title = x.title, x)),
then(x => fetchCategory(x.categoryId)),
then(x => this.category = x.category),
otherwise(console.error)
)(1)
}
export default {
name:'App',
data:() => ({
title: '',
category: '',
}),
methods:{
onClick
}
}
</script>
19 行
pipe(
fetchBook,
then(x => (this.title = x.title, x)),
then(x => fetchCategory(x.categoryId)),
then(x => this.category = x.category),
otherwise(console.error)
)(1)
使用將 Method Chaining 改成 Function Pipeline。
Conclusion
- Comma operator 過去較不受重視,但隨著 Promise Chain 流行後,我們常在
.then()
中只寫一行的 arrow function,此時可將 side effect 與 pure function 使用 comma operator 寫成一行