先直接上圖,打印一下Promise對象,觀察下Promise是什麼javascript
console.dir(Promise)
能夠知道,Promise是一個構造函數,有着reject、resolve函數。prototype有then、catch等方法,說明了只要是Promise對象都會有這兩個方法。html
Promise構造函數是傳入一個函數java
var promise = new Promise((resolve, reject) => { setTimeout(function () { console.log('執行完成'); resolve('隨便什麼數據'); }, 2000); }); result: 執行完成
傳入的函數有兩個參數:resolve、reject,分別表示異步操做執行成功後的回調函數和異步操做失敗後的回調函數。其實這裏用「成功」和「失敗」來描述並不許確,按照標準來說,resolve是將Promise的狀態置爲fullfiled,reject是將Promise的狀態置爲rejected。不過在咱們開始階段能夠先這麼理解,後面再細究概念。git
運行以上代碼,發現promise並無調用,只是new了一個Promise,對應的傳入函數的代碼就已經執行了。所以,咱們一般都是把Promise包在一個函數中,在須要的時候纔去運行這個函數,如:es6
function f() { var promise = new Promise((resolve, reject) => { setTimeout(function () { console.log('執行完成'); resolve('隨便什麼數據'); }, 2000); }); return promise } f() result: 執行完成
這時引出兩個問題。爲何須要大費周章的包裝這樣的一個函數?resolve有什麼用?編程
f().then(function(data){ console.log(data); //後面能夠用傳過來的數據作些其餘操做 //...... });
在f()的返回上能夠直接調用then方法,then接收一個參數,是函數,而且會拿到咱們在f中調用resolve時傳入的參數。運行這段代碼,會在2秒後輸出「執行完成」,緊接着輸出「隨便什麼數據」。promise
這時,咱們恍然大悟了,原來then調用的function至關於咱們以前寫的回調函數,至關因而這種形式:ecmascript
function runAsync(callback){ setTimeout(function(){ console.log('執行完成'); callback('隨便什麼數據'); }, 2000); } runAsync(function(data){ console.log(data); });
那使用Promise有什麼好處呢?咱們不妨考慮一個問題,若是callback函數也是一個異步操做,並且執行完後也須要有相應的回調函數,可能會變成 runAsync(function(data,function(data){}){.....})。看起來十分醜陋,假如使用Promise代碼就不會這麼醜陋了~異步
Promise的優點在於,能夠在then方法中繼續寫Promise對象並返回,而後繼續調用then來進行回調操做。函數
因此,從表面上看,Promise只是可以簡化層層回調的寫法,而實質上,Promise的精髓是「狀態」,用維護狀態、傳遞狀態的方式來使得回調函數可以及時調用,它比傳遞callback函數要簡單、靈活的多。因此使用Promise的正確場景是這樣的:
runAsync1() .then(function(data){ console.log(data); return runAsync2(); }) .then(function(data){ console.log(data); return runAsync3(); }) .then(function(data){ console.log(data); }); function runAsync1(){ var p = new Promise(function(resolve, reject){ //作一些異步操做 setTimeout(function(){ console.log('異步任務1執行完成'); resolve('隨便什麼數據1'); }, 1000); }); return p; } function runAsync2(){ var p = new Promise(function(resolve, reject){ //作一些異步操做 setTimeout(function(){ console.log('異步任務2執行完成'); resolve('隨便什麼數據2'); }, 2000); }); return p; } function runAsync3(){ var p = new Promise(function(resolve, reject){ //作一些異步操做 setTimeout(function(){ console.log('異步任務3執行完成'); resolve('隨便什麼數據3'); }, 2000); }); return p; } result: 異步任務1執行完成 隨便什麼數據1 異步任務2執行完成 隨便什麼數據2 異步任務3執行完成 隨便什麼數據3
咱們能夠經過鏈式編程避免了包含多函數回調的狀況,固然並非都須要return Promise對象,你也能夠返回其餘數據類型,在後面的then中就能直接直接接收到數據了,好比:
runAsync1() .then(function(data){ console.log(data); return runAsync2(); }) .then(function(data){ console.log(data); return '直接返回數據'; //這裏直接返回數據 }) .then(function(data){ console.log(data); }); result: 異步任務1執行完成 隨便什麼數據1 異步任務2執行完成 隨便什麼數據2 直接返回數據
前面咱們一直都是使用resolve函數,並無使用reject函數。resolve函數是表示了「執行成功」的回調,reject函數表示「執行失敗」的函數。
function runAsync1() { var p = new Promise(function (resolve, reject) { //作一些異步操做 setTimeout(function () { console.log('異步任務1執行完成'); // resolve('隨便什麼數據1'); reject("error") }, 1000); }); return p; } runAsync1().then((data) => { console.log('resolve'); console.log(data) }, (error, data) => { console.log('rejected'); console.log(error) }) result: 異步任務1執行完成 rejected error
須要注意的是,只要執行reject或者resolve,後面的就不會執行了,如:
function runAsync1() { var p = new Promise(function (resolve, reject) { //作一些異步操做 setTimeout(function () { console.log('異步任務1執行完成'); resolve('隨便什麼數據1'); reject("error") }, 1000); }); return p; }
由於resolve在reject的前面,因此只會執行resolve,不會執行reject。
ECMAScript6入門
大白話講解Promise(一)
ECMAScript6入門
署名
廣州蘆葦科技Java開發團隊
蘆葦科技-廣州專業互聯網軟件服務公司
抓住每一處細節 ,創造每個美好
關注咱們的公衆號,瞭解更多
想和咱們一塊兒奮鬥嗎?lagou搜索「 蘆葦科技 」或者投放簡歷到 server@talkmoney.cn 加入咱們吧
關注咱們,你的評論和點贊對咱們最大的支持