Promise是一個容器,裏面保存着某個將來纔會結束的時間(一般是一個異步操做的結果)編程
Promise對象的基本語法:數組
let p = new Promise((resolve, reject) => { // ... resolve('success') }) p.then(res => { console.log(res); // success })
Promise對象特色和三個狀態:promise
例如:瀏覽器
let p = new Promise((resolve, reject) => { // ... resolve('success') console.log('after resolve') reject('error') }) p.then(res => { console.log(res); // success }) p.catch(err => { console.log(err) }) // 運行結果:after resolve -> success
resolve下面的語句實際上是能夠執行的,那麼爲何reject的狀態信息在下面沒有接收到呢?這就是由於Promise對象的狀態凝固了。dom
new出一個Promise對象時,這個對象的起始狀態就是Pending狀態,再根據resolve或reject返回Fulfilled狀態/Rejected狀態。異步
Promise.prototype.then 的做用是爲Promise實例添加狀態改變時的回調函數。能夠有兩個參數async
Then分別接受resolve, reject的信息異步編程
let p = new Promise((resolve, reject) => { // ... let random = Math.random(); //小於1大於0 if (random > 0.4) { resolve('random > 0.4'); } else { reject('random <= 0.4'); } }) p.then(res => { console.log('resolve', res) }, res => { console.log('reject', res) })
Promise.resolve() 將現有對象轉爲Promise對象的快捷方式函數
let p1 = Promise.resolve({name: 'xixi', age: 18}) p1.then(result => { console.log(result) })
若是是Promise對象,直接返回spa
let p = new Promise((resolve, reject) => { setTimeout(() => { resolve('success') }, 500) }) let pp = Promise.resolve(p) pp.then(res => { console.log(res) }) console.log(pp == p) // 輸出結果:true -> success
Promise.reject() 快速地獲取一個拒絕狀態的Promise對象
let p = Promise.reject(123) console.log(p) p.then((res) => { console.log(res) }).catch(res => { console.log('catch', res) }) // 輸出結果:Promise {<rejected> 123} -> catch 123
let p1 = Promise.resolve(123); let p2 = Promise.resolve('hello'); let p3 = Promise.resolve('success'); Promise.all([p1, p2, p3]).then(result => { console.log(result); }) // 結果:[123, 'hello', 'success']
當全部的狀態都是成功狀態才返回數組,不然返回reject的狀態。
再來一個例子,用sleep模仿瀏覽器的AJAX請求
function sleep(wait) { return new Promise((res, rej) => { setTimeout(() => { res(wait) }, wait) }) } let p1 = sleep(500) let p2 = sleep(500) let p3 = sleep(1000) Promise.all([p1, p2, p3]).then(result => { console.log(result) // ... // loading })
Promise.race() 將多個Promise實例,包裝成一個新的Promise實例。哪一個對象返回的快就返回哪一個對象。race最終只有一個值。
異步編程的最高境界,就是根本不用關心它異步。
async函數就是隧道盡頭的亮光,不少人認爲它是異步操做的終極解決方案。
不存在誰替代誰的,由於async-await是寄生於Promise,Generator的語法糖
規則:
Promise雖然一方面解決了callback回調地獄,可是相對的把回調「縱向發展」了,造成了一個回調鏈。
舉例:
function sleep(wait) { return new Promise((res, rej) => { setTimeout(() => { res(wait) }, wait) }) } sleep(100).then(result => { return sleep(result + 100) }).then(result02 => { return sleep(result02 + 100) }).then(result03 => { console.log(result03) }) // 結果:300
後面的結果都是依賴前面的結果,改寫async/await寫法以下:
async function demo() { let result01 = await sleep(100) let result02 = await sleep(result01 + 100) let result03 = await sleep(result02 + 100) return result03 } demo().then(result => { console.log(result) }) // 結果:300
既然.then()不用寫了,那麼catch()也不用寫了,能夠直接用標準的try catch語法捕捉錯誤
若是是reject狀態,能夠用try-catch捕捉
let p = new Promise((resolve, reject) => { setTimeout(() => { reject('error') }, 1000) }) async function demo(params) { try { let result = await p } catch(e) { console.log(e) } } demo()
await in for循環
await的執行上下文必須是async函數
若是在forEach或者map的循環裏使用await,這時候上下文就變成了array,而不是async function 就會報錯。