Promise、Callbacks 和 Async/Await
首先,我們必須理解兩個主要概念
- 同步程式設計
- 非同步程式設計
同步程式設計
它等待每個語句完成執行,然後才執行下一個語句。
如果語句之間沒有依賴關係,但仍然需要等待執行(因為它們排隊),這種方法可能會降低應用程式的處理速度。
非同步程式設計
它不會等待當前語句完成執行,然後才執行下一個語句。例如,在 JavaScript 中呼叫 Web 服務和執行檔案複製。
呼叫 Web 服務可能需要一些時間才能返回結果,在此期間,我們可以完成其他操作。
一旦伺服器提供結果,我們就可以處理它,而無需等待。
我們的三種方法 1. Callbacks 2. Promises 3. Async/Await 處理非同步程式設計。
Callbacks
const articles = [
{title:'First article'},
{title:'Second article'}
];
function getArticles(){
setTimeout(()=>{
let articleContent='';
articles.forEach((article,index)=>{
articleContent+=`${article.title}`+` `;
});
console.log(articleContent);
},1000);
};
getArticles();在這裡,我們只是建立了一個文章陣列,並在 1 秒後將其列印到控制檯。
使用 setTimeout 函式和 1 秒的時間只是為了展示類似於伺服器的行為。
現在,如果我們透過另一個函式向上述列表中新增一篇新文章會怎樣?
function createArticle(article){
setTimeout(()=>{
articles.push(article);
},2000);
}如果我們現在用新文章呼叫 createArticle,然後呼叫 getArticle,我們應該得到三篇文章,但我們只得到前兩篇文章。
const articles = [
{title:'First article'},
{title:'Second article'}
];
function getArticles(){
setTimeout(()=>{
let articleContent='';
articles.forEach((article,index)=>{
articleContent+=`${article.title}`+` `;
});
console.log(articleContent);
},1000);
};
function createArticle(article){
setTimeout(()=>{
articles.push(article);
},2000);
}
createArticle({title:'Third article'});
getArticles();
//console output
"First article Second article "為什麼會這樣?
因為 createArticle 的執行有 2 秒的超時,在此期間,getArticle 完成了執行。
示例
const articles = [
{title:'First article'},
{title:'Second article'}
];
function getArticles(){
setTimeout(()=>{
let articleContent='';
articles.forEach((article,index)=>{
articleContent+=`${article.title}`+` `;
});
console.log(articleContent);
},1000);
};
function createArticle(article, callback){
setTimeout(()=>{
articles.push(article);
callback();
},2000);
}
createArticle({title:'Third article'},getArticles);
//console output
"First article Second article Third article "我們使用回撥將 getArticle 的呼叫巢狀在 createArticle 中。
請注意將 getArticles 作為引數傳遞給 createArticle 函式。但是,這樣巢狀回撥會變得很複雜。
Promises
使用 promises,我們不需要傳遞迴調函式。Promises 有兩個引數 resolve 和 reject。*如果函式成功執行,我們可以呼叫 resolve(),否則我們呼叫 reject()*
const articles = [
{title:'First article'},
{title:'Second article'}
];
function getArticles(){
setTimeout(()=>{
let articleContent='';
articles.forEach((article,index)=>{
articleContent+=`${article.title}`+` `;
});
console.log(articleContent);
},1000);
};
function createArticle(article){
return new Promise((resolve,reject)=>{
articles.push(article);
let isError=false;
if(!isError){
resolve();
} else {
reject();
}
});
}
createArticle({title:'Third article'})
.then(getArticles());
//console output
"First article Second article Third article "
handling error with promises:
const articles = [
{title:'First article'},
{title:'Second article'}
];
function getArticles(){
setTimeout(()=>{
let articleContent='';
articles.forEach((article,index)=>{
articleContent+=`${article.title}`+` `;
});
console.log(articleContent);
},1000);
};
function createArticle(article){
return new Promise((resolve,reject)=>{
articles.push(article);
let isError=true;
if(!isError){
resolve();
}else{
reject('Something went wrong');
}
});
}
createArticle({title:'Third article'})
.then(getArticles())
.catch(error=>console.log(error));
//console output
"Something went wrong"我們從 createArticle 呼叫了 reject 並捕獲了錯誤。
Promise All
const promise1=Promise.resolve('Hello');
const promise2=100;
const promise3=new Promise((resolve,reject)=>{
setTimeout(resolve,2000,'test');
});
Promise.all([promise1,promise2,promise3])
.then((values)=>console.log(values));
//console output
["Hello", 100, "test"]我們可以將 promises 組合到一個數組中,然後使用實際的 then 語句,而不是在每個 promise 後巢狀 then 語句。
我們可以將 fetch api 與 jsonplaceholder 一起使用。
const promise0=fetch('https://jsonplaceholder.typicode.com/users').then(res=>res.json());
const promise1=Promise.resolve('Hello');
const promise2=100;
const promise3=new Promise((resolve,reject)=>{
setTimeout(resolve,2000,'test');
});
Promise.all([promise0,promise1,promise2,promise3])
.then((values)=>console.log(values));Async / Await
要在語句上使用 await,該函式應標記為 async。
<!DOCTYPE html>
<html>
<head>
<title>Async/Await Example</title>
</head>
<body>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
const articles = [
{title:'First article'},
{title:'Second article'}
];
function getArticles(){
setTimeout(()=>{
let articleContent='';
articles.forEach((article,index)=>{
articleContent+=`${article.title}`+` `;
});
console.log(articleContent);
},1000);
}
function createArticle(article){
articles.push(article);
}
async function testAsync(){
await createArticle({title:'Third article'});
getArticles();
}
testAsync();
//console output
// First article Second article Third article
</script>
</body>
</html>testAsync 函式被標記為 async,我們使用 await 使 createArticle 函式首先完成。然後我們呼叫了 getArticles()。
使用 async / await 是 promises 的更好版本,並使其程式碼更簡潔。
資料結構
網路
RDBMS
作業系統
Java
iOS
HTML
CSS
Android
Python
C 程式設計
C++
C#
MongoDB
MySQL
Javascript
PHP