Promise 是非同步編程的一種方案,簡單說就是一個容器,裡面保存著某個未來才會結束的事件的 結果,Promise 是一個對象,從它,可以獲取非同步操作的消息。 Promise 對象有以下兩個特點。 (1)對象的狀態不受外界影響。Promise 對象代表一個非同步操作,有是三種狀態。pendding ( ...
Promise 是非同步編程的一種方案,簡單說就是一個容器,裡面保存著某個未來才會結束的事件的 結果,Promise 是一個對象,從它,可以獲取非同步操作的消息。 Promise 對象有以下兩個特點。 (1)對象的狀態不受外界影響。Promise 對象代表一個非同步操作,有是三種狀態。pendding (進行中),fulfilled(已成功)和rejected(已失敗)。 (2)一旦狀態改變,就不會在變,任何時候都可以得到這個結果,Promise 對象的狀態改變 只有兩種可能: 從pending 變為fulfilled 和pending 變為rejected.如果改變已經發生 了,你在 對Promise對象添加回調函數,也會立即得到這個結果。 Promise 有一些缺點,首先無法取消Promise ,一旦新建它就會立即執行,中途無法取消。 如果不設置回調函數,Promise內部拋出的錯誤,不會立即反應到外部。當處於pending 狀態時,無法得子目前進展到哪一個階段。 用法 Promise 對象是一個構造函數,用來生成Promise實例。 構造函數接受一個函數作為參數,該函數的兩個參數分別是resolve 和reject。 resolve 函數的作用是,將Promise 對象的狀態從“未完成”變為“成功”,在非同步操作成功 的時候調用,並將非同步操作的結果,作為參數參數傳遞。 reject 函數的作用是,將Promise對象的狀態從“未完成”變為“失敗”,在非同步操作失敗 的時候調用,並將非同步操作報出錯誤,作為參數傳遞出去。 Promise 實例陳倉以後,可以使用then 方法分別指定resolved狀態和rejected狀態回調函數。 例如: promise.then(function(value){ // success },function(error){ // failure }); 第一個回調函數是狀態變為resolved時調用, 第二個回調函數是Promise對象的狀態變為rejected時調用。 Promise對象的簡單例子。 funcion timeout(ms){ return new Promise((resolve,reject)=>{ setTimeout(resolve,ms,'done'); }); } timeout(100).then((value)=>{ console.log(value); }) Promise 建立後就會立即執行 let promise = new Promise(function(resolve,reject){ console.log('Promise'); resolve(); }); promise.then(function() { console.log('resolved.'); }); console.log('Hi'); // Promise // Hi! // resolved Promise.prototype.then() Promise 實例具有then 方法,也就是說,then方式定義在原型對象Promise.prototype上的。 then 方法返回的是一個新的Promise實例。 第一個參數是resolved狀態的回調函數, 第二個參數是rejected狀態的回調函數。 Promise.prototype.catch() Promise.prototype.catch 方法是.then(null,rejection)的別名,用於指定發生錯誤時的回調函數。 寫法一: const promise = new Promise(function(resolve,reject){ try { throw new Error('test'); }catch(e){ reject(e); } }); promise.catch(function(error){ console.log(error); }) // 寫法二 const promise = new Promise(function(resolve,reject){ reject(new Error('test')); }); promise.catch(function(error){ console.log(error); }) Promise.all() Promise.all 方法用於將多個Promise 實例,包裝成一個新的Promise實例。 const p = Promise.all([p1,p2,p3]); Promise.all 方法接受一個數組作為參數,p1,p2,p3都是Promise實例,如果不是,就會 調用下麵講到的Promise.resolve方法,將參數轉為Promise實例。 Promise.race() Promise.race 方法同樣是將多個Promise實例,包裝成一個新的Promise實例。 const p = Promise.race([p1,p2,p3]); 上面例子中,只要p1,p2,p3之中有一個實例率先改變狀態,p的狀態就跟著改變。 那麼率先改變的Promise實例的返回值,就傳給p的回調函數。 const p = Promise.race([ fatch('/resource-that-may-take-a-while'), new Promise(function(resolve,reject){ setTimeout(()=> reject(new Error('request timeout')),5000) }) ]); p.then(response => console.log(response)); p.catch(error => console.log(error)); 上面代碼中,如果5秒內fetch 方法無法返回結果,變數p的狀態就會變為rejected,從而 觸發catch 方法指定的回調函數。 Promise.resolve() 將現有對象轉為Promise對象。 Promise.resolve('foo') 等價於 new Promise(resolve =>resolve('foo')) Promise.resolve 方法的參數非常四種情況 1.參數一個Promise實例,將不做任何修改,原封不動地返回這個實例。 2.參數一個thenable 對象。 3.參數不是具有then方法的對象,或根本就不是對象。 4. 不帶任何參數。 Promise.reject(); Promise.reject(reason) 方法會返回一個新的Promise實例,該實例的狀態為rejected done() Promise對象的回調鏈,不管以then方法或是catch 方法結尾,要是最後一個方法拋出 錯誤,都有可能無法捕捉到。提供一個done方法,總是處於回調鏈的尾端,保證拋出 任何有可能出現的錯誤。 Promise.prototype.done = function (onFulfilled,onRejected){ this.then(onFulfilled,onRejected).catch(function(reason){ // 拋出一個全局錯誤 setTimeout(()=>{throw reason},0) }); } 應用載入圖片 const preloadImge = function(path){ return new Promise(function(resolve,reject){ const image = new Image(); image.onload = resolve; image.onerror = regect; image.src = path; }) };