JavaScript中Promise的使用
Promise是ES6中的函數,規範如何處理非同步任務的回呼函數,功能類似jQuery的defferred。簡單說就是透過promise物件的不同狀態呼叫不同的回呼函數。目前IE8及以下不支援,其他瀏覽器都支援。
promise物件的狀態,從Pending轉換為Resolved或Rejected之後,這個promise物件的狀態就不會再發生任何變化。
使用步驟:
var promise = new Promise(function(resolve, reject) { // 异步任务,通过调用resolve(value) 或 reject(error),以改变promise对象的状态;改变状态的方法只能在此调用。 //promise状态改变后,会调用对应的回调方法 }); promise.then(function(value){//resolve时的回调函数,参数由异步的函数传进来}) .catch(function(error){//发生异常时或明确reject()时的回调函数})
具體使用:
function getURL(URL) { //因为promise创建时即执行,所以用工厂函数封装promise对象 return new Promise(function (resolve, reject) { var req = new XMLHttpRequest(); req.open('GET', URL, true); req.onload = function () { if (req.status === 200) { resolve(req.responseText); } else { reject(new Error(req.statusText)); } }; req.onerror = function () { reject(new Error(req.statusText)); }; req.send(); }); } // 运行示例 var URL = "http://httpbin.org/get"; getURL(URL).then(function onFulfilled(value){ console.log(value); }).catch(function onRejected(error){ console.error(error); })
Promise的回呼只有非同步方式,即使是同步任務的回呼也是非同步執行 。
var promise = new Promise(function (resolve){ console.log("inner promise"); // 执行1:同步任务先执行 resolve(‘callBack'); }); promise.then(function(value){ console.log(value); // 执行3:虽然注册时状态为resolved,但回调仍是异步的; }); console.log("outer promise"); // 执行2:同步代码先执行
promise的方法鏈
then方法註冊的回調會依次被調用,每個then方法之間透過return 返回值傳遞參數。但回呼中的異常會導致跳過之間then的回調,直接呼叫catch的回調,之後再繼續呼叫剩下的then的回呼。在then(onFulfilled, onRejected)中,onFulfilled的異常不會被自己的onRejected捕獲,所以優先使用catch。
promise .then(taskA) .then(taskB) .catch(onRejected) .then(finalTask);
taskA拋異常,taskB被跳過,finalTask仍會被調用,因為
taskA拋異常,taskB被跳過,finalTask仍會被調用,因為taskA拋異常,taskB被跳過catch回傳的promise物件的狀態為resolved。
then方法內可以返回3種值
1. 返回另一個promise對象,下一個then方法根據其狀態選擇onFullfilled/onRejected回呼函數執行,參數仍由新promise的resolv /reject方法傳遞;
2. 傳回一個同步值,下一個then方法沿用當前promise物件的狀態,無需等非同步任務結束會立即執行;實參為上一then的回傳值;如果沒有return,則預設回傳undefined;
3. 拋出例外(同步/非同步):throw new Error('xxx');
then不僅是註冊一個回呼函數,還會將回調函數的回傳值進行變換,建立並傳回一個新promise物件。實際上Promise在方法鏈中的操作的都不是同一個promise物件。
var aPromise = new Promise(function (resolve) { resolve(100); }); var thenPromise = aPromise.then(function (value) { console.log(value); }); var catchPromise = thenPromise.catch(function (error) { console.error(error); }); console.log(aPromise !== thenPromise); // => true console.log(thenPromise !== catchPromise);// => true
Promise.all()靜態方法,同時進行多個非同步任務。在接收到的所有promise物件都變成FulFilled 或Rejected 狀態之後才會繼續進行後面的處理。
Promise.all([promiseA, promiseB]).then(function(results){//results是个数组,元素值和前面promises对象对应}); // 由promise对象组成的数组会同时执行,而不是一个一个顺序执行,开始时间基本相同。 function timerPromisefy(delay) { console.log('开始时间:”'+Date.now()) return new Promise(function (resolve) { setTimeout(function () { resolve(delay); }, delay); }); } var startDate = Date.now(); Promise.all([ timerPromisefy(100), //promise用工厂形式包装一下 timerPromisefy(200), timerPromisefy(300), timerPromisefy(400) ]).then(function (values) { console.log(values); // [100,200,300,400] });
不同時執行,而是一個接著一個執行promise
//promise factories返回promise对象,只有当前异步任务结束时才执行下一个then function sequentialize(promiseFactories) { var chain = Promise.resolve(); promiseFactories.forEach(function (promiseFactory) { chain = chain.then(promiseFactory); }); return chain; }
Promise.race()同all()類似,但是race()只要有一個promise物件進入FulFilled 或Rejected 狀態的話,就會執行對應的回呼函數。不過在第一個promise物件變成Fulfilled之後,並不影響其他promise物件的繼續執行。
//沿用Promise.all()的例子 Promise.race([ timerPromisefy(1), timerPromisefy(32), timerPromisefy(64), timerPromisefy(128) ]).then(function (value) { console.log(values); // [1] });
Promise.race()作為計時器的妙用
Promise.race([ new Promise(function (resolve, reject) { setTimeout(reject, 5000); // timeout after 5 secs }), doSomethingThatMayTakeAwhile() ]);
在then改變promise狀態
因為then的回呼中只有value參數,沒有改變狀態的方法(只能在構造方法的非同步任務中使用),要改變傳給下一個then的promise對象的狀態,只能重新new一個新的Promise對象,在非同步任務中判斷是否改變狀態,最後return出去傳給下一個then/catch。
var promise = Promise.resolve(‘xxx');//创建promise对象的简介方法 promise.then(function (value) { var pms=new Promise(function(resolve,reject){ setTimeout(function () { // 在此可以判断是否改变状态reject/resolve Reject(‘args'); }, 1000); }) return pms; //该promise对象可以具有新状态,下一个then/catch需要等异步结束才会执行回调;如果返回普通值/undefined,之后的then/catch会立即执行 }).catch(function (error) { // 被reject时调用 console.log(error) });
取得兩個promises的結果
//方法1:通过在外层的变量传递 var user; getUserByName('nolan').then(function (result) { user = result; return getUserAccountById(user.id); }).then(function (userAccount) { //可以访问user和userAccount }); //方法2:后一个then方法提到前一个回调中 getUserByName('nolan').then(function (user) { return getUserAccountById(user.id).then(function (userAccount) { //可以访问user和userAccount }); });
注意使用promise時的整體結構
假定doSomething()和doSomethingElse()都回傳了promise物件
#常用方式:
doSomething().then(doSomethingElse).then(finalHandler); doSomething |-----------------| doSomethingElse(resultOfDoSomething) //返回新promise,下一个then要收到新状态才执行 |------------------| finalHandler(resultOfDoSomethingElse) |---------------------|
常用變通方式:
doSomething().then(function () { return doSomethingElse();}).then(finalHandler); doSomething |-----------------| doSomethingElse(undefined) //then外层函数的arguments[0]== resultOfDoSomething |------------------| finalHandler(resultOfDoSomethingElse) |------------------|
錯誤方式1:
doSomething().then(function () { doSomethingElse();}).then(finalHandler); doSomething |-----------------| doSomethingElse(undefined) //虽然doSomethingElse会返回promise对象,但最外层的回调函数是return undefined,所以下一个then方法无需等待新promise的状态,会马上执行回调。 |------------------| finalHandler(undefined) |------------------|
錯誤方式2:
doSomething().then(doSomethingElse()).then(finalHandler); doSomething |-----------------| doSomethingElse(undefined) //回调函数在注册时就直接被调用 |----------| finalHandler(resultOfDoSomething) |------------------|

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

在日常生活中,我們常常會遇到承諾與兌現之間的問題。無論是在個人關係中,或是在商業交易中,承諾的兌現都是建立信任的關鍵。然而,承諾的利與弊也常常會引起爭議。本文將探討承諾的利與弊,並給予一些建議,如何做到言出必行。承諾的利是顯而易見的。首先,承諾可以建立信任。當一個人信守承諾時,他會讓別人相信自己是個可信賴的人。信任是人與人之間建立的紐帶,它可以讓人們更加

Vue是一款受歡迎的前端框架,在開發應用時經常會遇到各種各樣的錯誤和問題。其中,Uncaught(inpromise)TypeError是常見的一種錯誤型別。在本篇文章中,我們將探討它的產生原因和解決方法。什麼是Uncaught(inpromise)TypeError? Uncaught(inpromise)TypeError錯誤通常出現在

Promise.resolve()詳解,需要具體程式碼範例Promise是JavaScript中一種用來處理非同步操作的機制。在實際開發中,常常需要處理一些需要依序執行的非同步任務,而Promise.resolve()方法就是用來傳回一個已經Fulfilled狀態的Promise物件。 Promise.resolve()是Promise類別的靜態方法,它接受一個

瀏覽器相容性:哪些瀏覽器能夠支援Promise?隨著Web應用程式的複雜性不斷提高,開發人員迫切需要解決JavaScript中的非同步程式設計問題。過去,開發人員通常使用回調函數來處理非同步操作,但這會導致程式碼複雜且難以維護。為了解決這個問題,ECMAScript6引入了Promise,它提供了一種更直觀、更靈活的處理非同步操作的方式。 Promise是一種用於處理異

利用Promise對象,把普通函數改成返回Promise的形式,解決回調地獄的問題。明白Promise的成功失敗呼叫邏輯,可以靈活的進行調整。理解核心知識,先用起來,慢慢整合吸收知識。

promise物件狀態有:1、pending:初始狀態,既不是成功,也不是失敗狀態;2、fulfilled:意味著操作成功完成;3、rejected:意味著操作失敗。一個Promise物件一旦完成,就會從pending狀態變成fulfilled或rejected狀態,且不能再改變。 Promise物件在JavaScript中被廣泛使用,以處理如AJAX請求、定時操作等非同步操作。

Promise是一種用於處理非同步操作的程式設計模式,它是一種代表了非同步操作最終完成或失敗的對象,可以看作是對非同步操作的一種承諾,它可以更好地管理和組織非同步程式碼,使得程式碼更可讀性高、可維護性強。 Promise物件有三個狀態:pending、fulfilled和rejected。 Promise的核心思想是將非同步操作從回調函數中分離出來,透過鍊式呼叫的方式來表達非同步操作之間的依賴關係。
