一、什麼是promise?我們用promise解決什麼樣的問題 promise是非同步編程的一種解決方案:從語法上來說,Promise是一個對象,從他可以獲取非同步操作的信息;從本意上講,它是承諾,它承諾過一段時間會給你一個答覆。Promise有三種狀態:pending(等待態)、fulfiled(成功 ...
一、什麼是promise?我們用promise解決什麼樣的問題
promise是非同步編程的一種解決方案:從語法上來說,Promise是一個對象,從他可以獲取非同步操作的信息;從本意上講,它是承諾,它承諾過一段時間會給你一個答覆。Promise有三種狀態:pending(等待態)、fulfiled(成功態),rejected(失敗態);狀態一旦改變,就不會再變。創造promise實例後,它會立即執行。
Promise常常用來解決兩個問題:
- 回調地獄,代碼難以維護, 常常第一個的函數的輸出是第二個函數的輸入這種現象
- promise可以支持多個併發的請求,獲取併發請求中的數據
- 這個promise可以解決非同步的問題,本身不能說promise是非同步的
二、Promise 用法大全
1、基礎用法
let p = new Promise( (resolve, reject) => { console.log('我剛剛進來') setTimeout(() => { console.log('執行成功'); resolve('我是成功'); reject('我是失敗'); }, 2000); console.log('我在函數的末尾') }); p.then( (data) => { console.log(data) })
// 執行結果
// 我剛剛進來
// 我在函數的末尾
// 執行成功
// 我是成功
Promise的構造函數接收一個參數:函數,並且這個函數需要傳入兩個參數:
- resolve :非同步操作執行成功後的回調函數
- reject:非同步操作執行失敗後的回調函數
2、鏈式編程
p.then( (data) => { console.log(data); return '我是第一個then' }) .then( (data) => { console.log(data); return () => { console.log('我是第二個then的方法') } }) .then( (fun) => { fun(); })
所以,從錶面上看,Promise只是能夠簡化層層回調的寫法,而實質上,Promise的精髓是“狀態”,用維護狀態、傳遞狀態的方式來使得回調函數能夠及時調用,它比傳遞callback函數要簡單、靈活的多。所以使用Promise的正確場景是這樣的:
3、reject的用法(失敗狀態)
let p2 = new Promise( (resolve, reject) => { setTimeout(() => { let num = Math.ceil(Math.random() * 10); if (num > 5 ) { resolve(`${num}大於5,成功了`) } else { reject(`${num}小於5,失敗了`) } }, 2000) }); p2.then((data) => { console.log('resolve', data) }, (err) => { console.log('reject', err) }); // 執行結果 // reject 1小於5,失敗了 // resolve 8大於5,成功了
用來處理失敗的情況
4、catch的用法
我們知道Promise對象除了then方法,還有一個catch方法,它是做什麼用的呢?其實它和then的第二個參數一樣,用來指定reject的回調。用法是這樣:
p.then((data) => { console.log('resolved',data); console.log(err); //此處的err未定義 }) .catch((err) => { console.log('rejected',err); });
catch在Promise中的任何一步出現異常都不會卡死js的運行,而是會進入到這個catch中。catch類似於 try - catch;
5.all 的用法
let Promise1 = new Promise(function(resolve, reject){ setTimeout(() => { let num = Math.ceil(Math.random() * 10); if (1) { resolve(`${num}大於5,Promise1成功了`) } else { reject(`${num}小於5,Promise1失敗了`) } }, 2100) }) let Promise2 = new Promise(function(resolve, reject){ setTimeout(() => { let num = Math.ceil(Math.random() * 10); if (1 ) { resolve(`${num}大於5,Promise2成功了`) } else { reject(`${num}小於5,Promise2失敗了`) } }, 2200) }) let Promise3 = new Promise(function(resolve, reject){ setTimeout(() => { let num = Math.ceil(Math.random() * 10); if (1 ) { resolve({'ccc': `${num}大於5,Promise3成功了`}) } else { reject(`${num}小於5,Promise3失敗了`) } }, 2300) }) let pall = Promise.all([Promise1, Promise2, Promise3]) pall.then((data) => { console.log(data, '成功') }, (err) =>{ console.log(err, '失敗') }) // 執行結果 // [ '4大於5,Promise1成功了', // '8大於5,Promise2成功了', // { ccc: '9大於5,Promise3成功了' } ] '成功'
all方法: 誰跑的慢,就以誰為執行準執行回調。all接收一個數組參數,裡面的值最終都返回到Promise對象中。
有了all方法,就可以一次執行多個非同步操作,並且可以統一處理返回結果。例:在打開一個頁面是可以統一載入一些配置信息,比如下拉框選項等資源。
6、race用法
let p2 = new Promise( (resolve, reject) => { setTimeout(() => { let num = Math.ceil(Math.random() * 10); if (num > 5 ) { resolve(`${num}大於5,成功了`) } else { reject(`${num}小於5,失敗了`) } }, 5000) }); let Promise3 = new Promise(function(resolve, reject){ setTimeout(() => { let num = Math.ceil(Math.random() * 10); if (1 ) { resolve({'ccc': `我執行的快,就我了`}) } else { reject(`${num}小於5,Promise3失敗了`) } }, 2300) }) Promise.race([p2, Promise3]).then((data) =>{ console.log(data); }).catch((err) => { console.log(err); }); // { ccc: '我執行的快,就我了' }
reac用來處理載入超時的情況。