◆ JavaScript中的異步任務:
- JavaScript的執行環境是「單線程」
- 所謂單線程,是指JS引擎中負責解釋和執行JavaScript代碼的線程只有一個,也就是一次只能完成一項任務,這個任務執行完後才能執行下一個,它會「阻塞」其他任務。這個任務可稱爲主線程
- 異步模式可以一起執行多個任務
- JS中常見的異步調用
◆ promise:
- 主要解決異步深層嵌套的問題
- promise 提供了簡潔的API 使得異步操作更加容易
<script type="text/javascript">
/*
1. Promise基本使用
我們使用new來構建一個Promise Promise的構造函數接收一個參數,是函數,並且傳入兩個參數: resolve,reject, 分別表示異步操作執行成功後的回調函數和異步操作執行失敗後的回調函數
*/
var p = new Promise(function(resolve, reject){
//2. 這裏用於實現異步任務 setTimeout
setTimeout(function(){
var flag = false;
if(flag) {
//3. 正常情況
resolve('hello');
}else{
//4. 異常情況
reject('出錯了');
}
}, 100);
});
// 5 Promise實例生成以後,可以用then方法指定resolved狀態和reject狀態的回調函數
// 在then方法中,你也可以直接return數據而不是Promise對象,在後面的then中就可以接收到數據了
p.then(function(data){
console.log(data)
},function(info){
console.log(info)
});
</script>
◆ 基於Promise發送Ajax請求:
<script type="text/javascript">
/*
基於Promise發送Ajax請求
*/
function queryData(url) {
# 1.1 創建一個Promise實例
var p = new Promise(function(resolve, reject){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState != 4) return;
if(xhr.readyState == 4 && xhr.status == 200) {
# 1.2 處理正常的情況
resolve(xhr.responseText);
}else{
# 1.3 處理異常情況
reject('服務器錯誤');
}
};
xhr.open('get', url);
xhr.send(null);
});
return p;
}
# 注意: 這裏需要開啓一個服務
# 在then方法中,你也可以直接return數據而不是Promise對象,在後面的then中就可以接收到數據了
queryData('http://localhost:3000/data')
.then(function(data){
console.log(data)
# 1.4 想要繼續鏈式編程下去 需要 return
return queryData('http://localhost:3000/data1');
})
.then(function(data){
console.log(data);
return queryData('http://localhost:3000/data2');
})
.then(function(data){
console.log(data)
});
</script>
◆ Promise的基本API:
實例方法
.then()
.catch()
.finally()
<script type="text/javascript">
/*
Promise常用API-實例方法
*/
// console.dir(Promise);
function foo() {
return new Promise(function(resolve, reject){
setTimeout(function(){
// resolve(123);
reject('error');
}, 100);
})
}
// foo()
// .then(function(data){
// console.log(data)
// })
// .catch(function(data){
// console.log(data)
// })
// .finally(function(){
// console.log('finished')
// });
// --------------------------
// 兩種寫法是等效的
foo()
.then(function(data){
# 得到異步任務正確的結果
console.log(data)
},function(data){
# 獲取異常信息
console.log(data)
})
# 成功與否都會執行(不是正式標準)
.finally(function(){
console.log('finished')
});
</script>
◆ 靜態方法:
.all()
Promise.all
方法接受一個數組作參數,數組中的對象(p1、p2、p3)均爲promise實例(如果不是一個promise,該項會被用Promise.resolve
轉換爲一個promise)。它的狀態由這三個promise實例決定
.race()
Promise.race
方法同樣接受一個數組作參數。當p1, p2, p3中有一個實例的狀態發生改變(變爲fulfilled
或rejected
),p的狀態就跟着改變。並把第一個改變狀態的promise的返回值,傳給p的回調函數
<script type="text/javascript">
/*
Promise常用API-對象方法
*/
// console.dir(Promise)
function queryData(url) {
return new Promise(function(resolve, reject){
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if(xhr.readyState != 4) return;
if(xhr.readyState == 4 && xhr.status == 200) {
// 處理正常的情況
resolve(xhr.responseText);
}else{
// 處理異常情況
reject('服務器錯誤');
}
};
xhr.open('get', url);
xhr.send(null);
});
}
var p1 = queryData('http://localhost:3000/a1');
var p2 = queryData('http://localhost:3000/a2');
var p3 = queryData('http://localhost:3000/a3');
Promise.all([p1,p2,p3]).then(function(result){
// all 中的參數 [p1,p2,p3] 和 返回的結果一 一對應["HELLO TOM", "HELLO JERRY", "HELLO SPIKE"]
console.log(result) //["HELLO TOM", "HELLO JERRY", "HELLO SPIKE"]
})
Promise.race([p1,p2,p3]).then(function(result){
// 由於p1執行較快,Promise的then()將獲得結果'P1'。p2,p3仍在繼續執行,但執行結果將被丟棄。
console.log(result) // "HELLO TOM"
})
</script>
◆ async 和 await:
- async作爲一個關鍵字放到函數前面
- 任何一個
async
函數都會隱式返回一個promise
await
關鍵字只能在使用async
定義的函數中使用
- await後面可以直接跟一個 Promise實例對象
- await函數不能單獨使用
- async/await 讓異步代碼看起來、表現起來更像同步代碼
# 1. async 基礎用法
# 1.1 async作爲一個關鍵字放到函數前面
async function queryData() {
# 1.2 await關鍵字只能在使用async定義的函數中使用 await後面可以直接跟一個 Promise實例對象
var ret = await new Promise(function(resolve, reject){
setTimeout(function(){
resolve('nihao')
},1000);
})
// console.log(ret.data)
return ret;
}
# 1.3 任何一個async函數都會隱式返回一個promise 我們可以使用then 進行鏈式編程
queryData().then(function(data){
console.log(data)
})
#2. async 函數處理多個異步函數
axios.defaults.baseURL = 'http://localhost:3000';
async function queryData() {
# 2.1 添加await之後 當前的await 返回結果之後纔會執行後面的代碼
var info = await axios.get('async1');
#2.2 讓異步代碼看起來、表現起來更像同步代碼
var ret = await axios.get('async2?info=' + info.data);
return ret.data;
}
queryData().then(function(data){
console.log(data)
})