回調地獄demo
function getData({ url, success }) {
const xhr = new XMLHttpRequest()
xhr.open('get', url)
xhr.onreadystatechange = function () {
if (this.readyState === 4) {
// 加載完成
const d = JSON.parse(xhr.responseText);
success(d)
}
}
xhr.send()
}
getData({
url:'http://localhost:3000/get',
success: (data)=>{
getData({
url:'http://localhost:3000/getCategory?id='+data[0].id,
success: data => {
getData({
url:'http://localhost:3000/getNews?id='+data[0].id,
success: data => {
console.log(data)
}
})
}
})
}})
promise的基本使用
- 構造器必須要定一個參數,如果不給就是報錯.例如,new promise()報錯資訊就是:Promise resolver undefined is not a function這不是一個函數
- 構造器的實參是一個函數,這個函數的特殊在于他有兩個形參
- 在函數的内部,一般會執行異步代碼,然後根據情況來調用
var p1 = new Promise(function(resolve,reject){
//異步操作 resolve(obj1) 或者 reject(obj2)
});
p1.then(function(rs){
// 如果p1的狀态是resolved,則then中的函數
//會執行,且obj1的值會傳給rs
}).catch(function(rs){
// 如果p1的狀态是reject,則catch中的函數
// 會執行,且obj2的值會傳給rs
}).finally(function(){
// 一定會執行的函數
})
三種狀态和值
promise的三種狀态
pending:待定剛剛開始一個初始狀态
resolved:成功表示承諾的東西實作了從pending狀态到了resolved
rejected :表示承諾的東西失敗了沒有實作
三種狀态的轉換
pending----resolve----resolved
pending----reject----rejected
三種狀态轉換是不可逆的
使用promise改造回調函數
- 第一步:建立模闆.這裡的末班是指固定的套路:寫一個空函數,在函數體中建立一個promise對象并傳回
- 第二步:把一部功能寫入構造器中,根據實際來決定是否調用resolve,reject
- 第三步:調用函數通過fnName().then().catch()結構來調用這個函數
改寫上面的代碼
function getDataPromise(url) {
let p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open('get', url)
xhr.onreadystatechange = function () {
if (this.readyState === 4) {
// 加載完成
const d = JSON.parse(xhr.responseText);
resolve(d)
}
}
xhr.send()
})
return p
}
then的格式及執行邏輯
p.then(函數1[,函數2])
第一個參數是resolved狀态回調函數
第二個是rejected狀态的回調函數
執行邏輯
- 如果promise對象的狀态是resolved,則then()會執行第一個函數,并傳入目前的PromiseValue
- 如果promise對象的狀态是rejected,則then()會執行第二個函數,并傳入目前的PromiseValue
- 特别地,如果promise對象的狀态是rejected,且此時then方法并沒有設定第二個參數,就會向外抛出一個錯誤,錯誤的提示大約是Uncaught (in promise)
catch的格式及用法
catch 是 then(null, reject)的别名
一般與then一塊使用,單獨使用無意義
async-await的文法
async,await是es7中的新增文法,用來改進異步代碼寫法,是promise更新版
- async函數傳回一個promise對象
- async函數内部return語句傳回的值是promise對象的值
await指令
- await的外層函數必須有一個async
- 正常情況下,await指令後面是一個promise對象,傳回該promise的值.如果不是promise對象就直接傳回對應的值
使用async來優化回調地獄
async function fn() {
const res = await getDataPromise('http://localhost:3000/get')
console.log('第1次成功', res)
const res1 = await getDataPromise('http://localhost:3000/getCategory?id=' + res[0].id)
console.log('第2次成功', res1)
const res2 = await getDataPromise('http://localhost:3000/getNews?id=' + res1[0].id)
console.log('第3次成功', res2)
}
fn()