Async
Syntaxes for async await
, Promise + then
, and handle errors properly
// Await
async function asyncCall() {
try {
const res = await oneSec(1000)
// a good practice to check res.ok as soon as you receive the response from a fetch call,
// bc the `res` body might be invalid JSON, and below `res.json()` will lead to an error
if (!res.ok) throw new Error(res.status) // e.g. res = { ok: false, status: 404, statusText: "Not Found"}
const data = await res.json()
console.log(data)
} catch (err) {
// The above Error will be caught here
// Here we can handle it appropriately, DON'T THROW AGAIN
reportError({ message: getErrorMessage(err) })
}
}
// Promise with `then`
// Thường ko cần param thứ 2 `err`, trừ những lỗi phải dc xử lý ngay lập tức.
oneSec(2000)
.then(
(res) => {
if (!res.ok) throw new Error(res.status)
return res.json()
},
// (err) => 'deal with the error immediately',
)
.then((data) => console.log(data))
.catch((err) => {
reportError({ message: getErrorMessage(err) })
})
function getErrorMessage(error: unknown) {
// `Error` is a built-in type: { name: string; message: string; stack?: string }
if (error instanceof Error) return error.message
return `${error}`
}
const reportError = ({ message }: { message: string }) => {
// send the error to our logging service...
}
Promise
explain
// Log 1 3 2
new Promise((resolve) => {
console.log(1)
resolve(2)
}).then((result) => console.log(result))
console.log(3)
// Async function always return a promise. If not, it will be wrapped in a Promise
async function foo() {
return 1
} // Equalivent to this. Note that this doesn't have `async` keyword
function foo2() {
return Promise.resolve(1)
}
// We don't need `async` here because the fn returns a promise
function oneSec(duration) {
return new Promise((resolve, reject) => {
if (duration === 1000)
setTimeout(
// Resolve with `json` method to simulate typical `fetch` response
() => resolve({ json: () => `{ "id": 1, "title": "vip" }` }),
1000,
)
else reject(new RangeError('Error: duration !== 1000'))
})
}
Promise
methods
const fetchDetails = async () => {
const fetchPromises = ids.map((id) => fetch(getJobDetailURL(id)))
const responses = await Promise.all(fetchPromises)
const jsonPromises = responses.map((res) => res.json())
const data = await Promise.all(jsonPromises)
}
// .all -> All must fullfill
// .allSettled -> All must settle (fulfilled or rejected)
//. any -> Return the first fulfilled promise
//. race -> Return the first settled promise
Axios vs Fetch
Fetch phải tốn thêm 1 lần .json()
, ngoài ra trong các lệnh như POST, PATCH,... phải convert data bằng JSON.stringify
. Fetch thì phải check response.ok
rồi mới catch
error còn Axios thì catch
trực tiếp luôn.
- POST
- GET
- PUT
- PATCH
- Concurrent
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
headers: {
'Content-type': 'application/json', // `fetch` default is 'text/plain'
// we don't need this in axios because its default is 'application/json'
},
body: JSON.stringify({
email: '@gmail.com',
}),
})
.then((res) => {
if (!res.ok) throw new Error(res.status)
return res.json()
})
.then((data) => console.log(data))
.catch((err) => console.log(err))
axios
.post('https://jsonplaceholder.typicode.com/posts', {
email: '@gmail.com',
})
.then((res) => console.log(res.data))
.catch((error) => console.log(error))
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then((res) => res.json())
.then((res) => {
if (!res.ok) throw new Error(res.status)
return res.json()
})
.then((data) => console.log(data))
.catch((err) => console.log(err))
axios
.get('https://jsonplaceholder.typicode.com/todos/1')
.then((res) => console.log(res.data))
.catch((err) => console.log(err))
// Replace a resource
fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'PUT',
body: JSON.stringify({
id: 1,
title: 'foo',
body: 'bar',
userId: 1,
}),
headers: {
'Content-type': 'application/json; charset=UTF-8',
},
})
.then((res) => res.json())
.then((data) => console.log(data))
// Modify a resource thay vì replace như PUT
fetch('https://jsonplaceholder.typicode.com/posts/1', {
method: 'PATCH',
body: JSON.stringify({
title: 'Vip pro',
}),
headers: {
'Content-type': 'application/json; charset=UTF-8',
},
})
.then((res) => res.json())
.then((data) => console.log(data))
Promise.all([
fetch('https://jsonplaceholder.typicode.com/posts/1'),
fetch('https://jsonplaceholder.typicode.com/posts/2'),
]).then((responses) =>
responses.forEach(async (res) => {
const data = await res.json()
console.log(data)
}),
)
Promise.all([
axios.get('https://jsonplaceholder.typicode.com/posts/1'),
axios.get('https://jsonplaceholder.typicode.com/posts/2'),
]).then((responses) => responses.forEach((res) => console.log(res.data)))