Callback hell
a common callback hell in js:
setTimeout(() =>{
console.log("One Second");
setTimeout(() =>{
console.log("Two Seconds");
setTimeout(() =>{
console.log("Three Seconds");
setTimeout(() =>{
console.log("Four Seconds");
setTimeout(() =>{
console.log("Five Seconds");
}, 1000)
}, 1000)
}, 1000)
}, 1000)
}, 1000)
We can escape this callback hell using something call Promises in asynchronous JavaScript.
What a Promise
A promise is placeholder for the future result of an asynchronous operation. In simple words, we can say it is a container for a future value.
When a promise is created it runs asynchronously.
When the given task is completed, then we say the promise is settled.
After the promise is settled, we can have either a fulfilled or rejected promise state based on the outcome of the promise.
We can handle these different states in different ways in our code.
How to Consume Promises: then()
We can consume a promise using the then()
method on the promise.
Producing code is code that can take some time to complete. Consuming code is code that must wait for the result.
Using multiple then()
methods on a single request is called chaining promises, which helps us reduce callback hell.
How to Handle Rejected Promises: catch()
Now we will learn to handle error on Promise. We used then()
to consume our promises. Similar to that, we will chain the catch()
method to that promise.
注意,then()
和catch()
都是用来注册回调函数的
example.js:
function call(){
const request = fetch('https://course-api.com/react-store-products').then((response) =>{
console.log(response);
return response.json()
}).then((data) =>{
console.log(data);
}).catch((err) =>{
console.log(err);
}).finally(() =>{
console.log("Will always run");
})
}
const btn = document.querySelector("button")
btn.addEventListener("click", function(){
call();
})
How to Consume Promises using async/await (recommended)
为什么需要async/await
?
因为它比then
更加直观,可以通过同步的语法表达来实现异步逻辑
我们用async/await
重写上面的发起http请求并获取响应的代码:
const fetchAPI = async function(){
try{
const res = await fetch('https://cat-fact.herokuapp.com/fact')
if(!res.ok){
throw new Error("Custom Error")
}
const data = await res.json()
console.log(data);
} catch(err){
console.log(err);
}
}
fetchAPI()
console.log("FIRST");
整个逻辑非常直观
注意:await本身是blocking的,
const res = await fetch('https://cat-fact.herokuapp.com/fact')
这一行是阻塞的。因此,如果需要使用await,必须把await封装在一个async函数里面。一个异步函数内部的blocking是无关紧要的
How to create Promises
Once you know how to create promises, you can make any piece of code asynchronous.
First we created a promise using new Promise()
. It will have a function with two arguments, resolve
and reject
.
We will call resolve
when our task is successful, and reject
when the task is unsuccessful.
resolve
是将Promise的状态置为fullfiled
,reject
是将Promise的状态置为rejected
promise.js:
let lottery = new Promise(function(resolve, reject){
console.log("Lottery is happening");
setTimeout(() => {
if(Math.random() >= 0.5){
resolve("You Won!!!") // Promise的data就是"You Won!!!"
}
else{
reject(new Error("Better luck next time"))
}
}, 5000);
})
lottery.then((response) =>{
console.log(response);
}).catch((err) =>{
console.log(err);
})
另外,一个被async修饰的func也会自动包装一个Promise作为返回
conclusion
In JavaScript, there are two common ways to work with asynchronous operations:
then/catch
method chaining and async/await
. Both methods can be used to handle promises, which are objects that represent the eventual completion (or failure) of an asynchronous operation.
then/catch
method chaining is a more traditional way to handle asynchronous operations, while async/await
is a newer syntax that provides a more concise and easier-to-read alternative.
网友评论