Promise 是一種非同步程式設計解決方案,它比傳統解決方案(函式和事件)更有意義且更健壯。 它最初是由社群提出並實現的,ES6 已經將其寫入語言標準,統一了用法,並原生提供了 promise 物件。
Promise 物件有兩個特徵。
(1)物體的狀態不受外界影響。
promise 物件表示非同步操作有三種狀態:待處理、已解決(也稱為已履行)和拒絕。只有非同步操作的結果才能確定它所處的狀態,沒有其他操作可以更改此狀態。 這就是“promise”這個名字的由來,在英語中是“promise”的意思,意思是不能通過其他方式改變。
(2)狀態一旦改變,就不會再改變,這個結果可以隨時得到。
promise 物件只有兩種可能性:從掛起到已解決,從掛起到拒絕。只要這兩種情況發生,狀態就會固化,不會再改變,並且會一直保持這個結果。 即使更改已經發生,您也可以向 promise 物件新增乙個函式,您將立即得到此結果。 這與事件完全不同,事件的特點是,如果你錯過了它並聽了它,你就不會得到結果。
使用 promise 物件,您可以在同步操作流中表示非同步操作,從而避免巢狀函式層。 此外,promise 物件提供了乙個統一的介面,可以更輕鬆地控制非同步操作。
承諾也有一些缺點。 首先,乙個承諾是不能取消的,一旦有了新的承諾,就會立即執行,不能半途而廢。 其次,如果不設定 ** 函式,promise 內部丟擲的錯誤不會反映到外部。 第三,當處於待處理狀態時,沒有辦法知道你目前處於哪個階段(剛剛開始或即將結束)。
示例 1:基本用法。
var promise = new promise(function(resolve, reject) else }示例 2:一旦做出新的承諾,它將立即執行。
let promise = new promise(function(resolve, reject) )promise.then(function() console.log('hi!'); // promise // hi! // resolved示例 3:下面是使用 promise 物件實現的 AJAX 操作的示例。 (非常經典)。
var getjson = function (url) if (this.status === 200) else }return promise; }getjson("/posts.json").then(function (json) ,function (error) )promise 例項有乙個 then 方法,即 then 方法在原型物件 promise 中定義原型。 它的作用是在狀態更改時向 promise 例項新增乙個函式。 如前所述,then 方法的第乙個引數是已解析狀態的函式,第二個引數(可選)是被拒絕狀態的函式。
then 方法返回乙個新的 promise 例項(請注意,它不是原始 promise 例項)。 因此,您可以使用鏈式方法,其中 then 方法後面跟著另乙個 then 方法。
getjson("/posts.json").then(function(json) )then(function(post) )使用 chained then,可以指定一組按順序呼叫的函式。 在這種情況下,前乙個函式可能仍會返回乙個 promise 物件(即存在非同步操作),而後乙個函式將等待 promise 物件的狀態發生變化後再呼叫。
getjson("/post/1.json").then(function (post) )then(function funca(comments) ,function funcb(err) )在上面的第乙個 then 方法中,第乙個 then 方法指定的函式返回另乙個 promise 物件。 在本例中,第二個 then 方法指定乙個函式,該函式等待新 promise 物件的狀態發生更改。 如果它被解析,它呼叫 funca,如果狀態變為 rejected,則呼叫 funcb。
promise.prototype.catch 方法是。 then(null, rejection) 指定發生錯誤時的 ** 函式。
例:
getjson("/posts.json").then(function (posts) )catch(function (error) )與傳統的 try catch 塊不同,如果沒有使用 catch 方法指定錯誤處理的函式,promise 物件丟擲的錯誤不會傳遞到外層,即不會有任何反應。
var someasyncthing = function ()someasyncthing().then(function ()promise.all 方法用於將多個 promise 例項包裝到乙個新的 promise 例項中。
var p = promise.all([p1, p2, p3]);
以上,承諾all 方法接受陣列作為引數,p1、p2 和 p3 都是 promise 物件的例項。
例:
promise.all([checklogin(),getuserinfo()]then(([res1,res2])=>, result2:$`promise.race(iterable) 方法返回乙個 promise,一旦迭代器中的承諾被解析或拒絕,該 promise 就會被解析或拒絕。
有時你需要將乙個現有的物件轉換為乙個 promise 物件,乙個 promise這就是 resolve 方法的用武之地。
var jspromise = promise.resolve($.ajax('/whatever.json'));promise.reject(reason) 方法還返回乙個狀態為 rejected 的新 promise 例項。 它的論點與承諾的使用方式相同resolve 方法是相同的。
ES6 的 promise API 沒有提供很多方法,有一些有用的方法可以自己部署。 以下是如何部署兩個不屬於 ES6 的有用方法。
9.1. done()promise 物件的 ** 鏈,無論以 then 方法還是 catch 方法結尾,如果最後乙個方法丟擲錯誤,它可能不會被捕獲(因為 promise 裡面的錯誤不會冒泡到整個世界)。 因此,我們可以提供乙個 done 方法,它始終位於鏈的末端,並保證丟擲可能發生的任何錯誤。
asyncfunc() then(f1) .catch(r1) .then(f2) .done();9.2. finally()finally 方法用於指定將要執行的操作,而不管 promise 物件的最終狀態如何。 它與 done 方法最大的區別在於它接受乙個普通的 ** 函式作為引數,無論如何都必須執行。
server.listen(0) .then(function ()finally(server.stop);生成器函式用於管理程序,當遇到非同步操作時,通常會返回乙個 promise 物件。
function getfoo() var g = function* (catch (e) function run(generator) ,function (error) )go(it.next())run(g);超詳細的 Promise 理解與實現前端 Promise 常見應用場景正確理解 Promise 執行過程的態勢 [J**Ascript]手寫 Promise 必須能夠深入揭開 Promise 微任務註冊和執行流程的神秘面紗Promise 原理與實現超詳細的 Promise 理解與實現前端 Promise 常見應用場景正確理解 Promise 執行過程的態勢【J** ascript】一定能夠要編寫手寫承諾,請新增:承諾allsettled()
直接參考文件: