例如我有一個A.func1()是異步的,它能回傳一個物件x1,我還有一個B.func2()也是異步的,需要根據x1來執行,然後B.func2回傳一個最終值值t ,根據這個最終值t就進行一些提示性顯示。請問這個要怎麼寫呢?
我自己寫的程式碼是這樣的
A.func1().
then(function(x1) {
B.func2(x1).
then(function(t) {
//do something
})
})
但覺得這樣用不用then就一個效果啦…還是變回金字塔了
針對評論裡的補充的“promise連續調用過程中保存狀態”,我想詳細說幾種策略
上策:去狀態化
也就是調整你的邏輯,讓A.func1,B.func2,和後面那個匿名函數(就叫func3吧)的呼叫過程不含狀態,也就是讓func3只依賴func2的輸出,不依賴func1的輸出;又或著讓func2不依賴func1,用類似
Promise.all
來同時拿到func1和func2的結果丟給func3中策:「全域」變數維護狀態
優點:state可擴充state.x2 .x3 ...
問題:很長的呼叫鏈帶複雜狀態的話,很容易污染出bug,程式碼可維護性下降嚴重
bluebird
的bind方法可以綁定thisArg,可以用來保留狀態,原理是一樣的中策:臨時額外傳遞
優點:不帶狀態,如果呼叫鏈很長,這個額外狀態被控制在兩步驟之間,保持了較好的可維護性,不易出bug
缺點:如果長調用鏈的每步都有狀態,會變得無比囉嗦
當然這裡的內層then也可以自己包裝一下優化掉
下策:閉包維護狀態
其實就是題主原來的寫法,我覺得主要的問題就是題主說的又降級回到了原本的“callback hell”或者說回調金字塔的難堪之中了
優點是…it works
直接在
then
里面返回一个Promise
的對象,如下:針對你評論中說的問題,如果不使用第三方的
Promise
庫的話,可以像下面這樣使用:使用第三方的
Promise
函式庫可以簡化這個過程。promise會傳回promise對象,這樣才使得它可以使用優雅的鍊式呼叫。
then裡面的函數的返回值如果是一個直接量,則會作為下一個鍊式調用的then的參數
如果返回值具有promise的接口,則返回該promise的resolve的結果
用q做個例子