一般來說呼叫 API 的 Asynchronous 才會遇到 Promise,也才需要 Error Handling,但 SweetAlert2 按下 Confirm
時回傳 Fulfilled Promise,按下 Cancel
時回傳 Rejected Promise,此時會進入處理 API 的 Error Handling,這該如何解決呢 ?
Version
macOS Catalina 10.15.6
WebStorm 2020.2
Ramda 0.27.0
Vue 2.6.11
SweetAlert 6.11.4
Promise Chain
<template>
<div>
<button class="btn btn-primary" @click="onSubmit">Submit</button>
{{ msg }}
</div>
</template>
<script>
import swal from 'sweetalert2'
import axios from 'axios'
let fetchBook = x => axios.get(`http://localhost:3000/books/${x}`)
.then(x => x.data)
let onSubmit = function() {
let errorHandling = e => {
if (e === 'cancel') {}
else if (e.response)
console.log(e.response.status)
else
console.log(e)
}
swal({
title: 'Are you sure?',
type: 'warning',
showCancelButton: true,
confirmButtonClass: 'btn btn-success btn-fill',
cancelButtonClass: 'btn btn-danger btn-fill',
confirmButtonText: 'Confirm',
buttonsStyling: false
}).then(() => 1)
.then(fetchBook)
.then(x => this.msg = x.title)
.catch(errorHandling)
}
export default {
name: 'App',
data: () => ({
msg: ''
}),
methods: {
onSubmit
}
};
</script>
25 行
swal({
title: 'Are you sure?',
type: 'warning',
showCancelButton: true,
confirmButtonClass: 'btn btn-success btn-fill',
cancelButtonClass: 'btn btn-danger btn-fill',
confirmButtonText: 'Confirm',
buttonsStyling: false
}).then(() => 1)
.then(fetchBook)
.then(x => this.msg = x.title)
.catch(errorHandling)
SweetAlert 的 swal()
回傳 Promise,若按下 Confirm
接著要打 API,因此可在 .then()
之後呼叫 fetchBook()
。
16 行
let errorHandling = e => {
if (e === 'cancel') {}
else if (e.response)
console.log(e.response.status)
else
console.log(e)
}
當按下 cancel
時,swal()
會回傳 Rejected Promise,因此進入 .catch()
的 errorHandling()
。
關鍵在於按下 cancel
時,Rejected Promise 內部值為 cancel
,因此可藉此判斷是來自於 swal()
的 Rejected Promise,還是來自於 axios.get()
的 Rejected Promise。
Ramda
<template>
<div>
<button class="btn btn-primary" @click="onSubmit">Submit</button>
{{ msg }}
</div>
</template>
<script>
import swal from 'sweetalert2'
import axios from 'axios'
import { pipe, andThen as then, otherwise, always } from 'ramda'
let fetchBook = x => axios.get(`http://localhost:3000/books/${x}`)
.then(x => x.data)
let onSubmit = function() {
let swalBody = {
title: 'Are you sure?',
type: 'warning',
showCancelButton: true,
confirmButtonClass: 'btn btn-success btn-fill',
cancelButtonClass: 'btn btn-danger btn-fill',
confirmButtonText: 'Confirm',
buttonsStyling: false
}
let errorHandling = e => {
if (e === 'cancel') {}
else if (e.response)
console.log(e.response.status)
else
console.log(e)
}
pipe(
swal,
then(always(1)),
then(fetchBook),
then(x => this.msg = x.title),
otherwise(errorHandling)
)(swalBody)
}
export default {
name: 'App',
data: () => ({
msg: ''
}),
methods: {
onSubmit
}
};
</script>
36 行
pipe(
swal,
then(always(1)),
then(fetchBook),
then(x => this.msg = x.title),
otherwise(errorHandling)
)(swalBody)
既然 swal()
回傳為 Promise,因此可直接在 Ramda 的 pipe()
內使用 swal()
,讓 swal()
與 fetchBook()
一起 Function Pipeline。
Error handling 部分則完全一樣。
Conclusion
- 遇到有 function 回傳 Rejected Promise 時不用擔心,只要清楚知道 Rejected Promise 內部值為何,就可以加以判斷與
axios.get()
的 Rejected Promise 分開處理