我有一個分頁 API,我需要它來自動獲取每頁結果。
我構建了以下遞回承諾鏈,它實際上為我提供了所需的輸出。我已將傳統決議重命名為外部,以嘗試將我的頭更多地圍繞它,但我仍然對如何將外部函式傳遞到嵌套的 .then 感到困惑。那么是允許它作業的魔法嗎?
我以為我很了解 Promises 但顯然不是!
protected execute<T>(httpOptions): Promise<AxiosResponse | T> {
const reqObject: HttpConfig = {
...httpOptions,
baseURL: this.config.baseUri,
headers: { Authorization: `Bearer ${this.config.apiKey}` },
};
return new Promise((outer, reject) => {
axios
.request<T>(reqObject)
.then((res) => {
if (res.headers.link) {
const pagingObject: PagingObject = this.getPagingObject(res);
this.pagedListResponses = this.pagedListResponses.concat(res.data);
if (pagingObject.last) {
this.execute<T>({
url: pagingObject.next,
}).then(outer);
} else {
outer(this.pagedListResponses as any);
}
} else {
outer("No paging header found");
}
})
.catch((err) => reject(err));
});
}
uj5u.com熱心網友回復:
承諾鏈
當一個 Promise 物件在另一個 Promise的Resolve處理程式中創建時,兩個 Promise 都以由內而外的順序結算。另外,當鏈通過無極實體方法(使用.then(),.catch(),。 always(),等),鏈式方法優先和最外無極物件結算前被執行。
也許在這里解釋得更好。
您的代碼在外部構造的 Promise 物件的 Resolve 處理程式中創建 Axios Promise。AxiosPromise.then()將在外部 Promise 最終解決之前執行。之后,結果將通過外部 Promise 物件而無需修改或處理。基本上沒有操作。
這就是為什么包裝器 Promise(顯式構造反模式)是不必要的和不鼓勵的 - 這是對時間和資源的浪費,在此代碼中沒有任何好處。
混合使用遞回,Promise 物件只會越來越多。
因此(目前)從該.execute()方法回傳對該外部 Promise 物件的參考。但是何時/如何解決(解決或拒絕)?
- Axios Promise 使用 AJAX 結果決議
- 如果這是一個遞回呼叫,則這是一個內部 Promise(即使
.then(outer)在這種情況下使用它創建更令人困惑)
- 如果這是一個遞回呼叫,則這是一個內部 Promise(即使
.then()使用 AJAX 結果呼叫最外層(或有理由拒絕)- 實體變數
pagedListResponses用結果更新 - 如果
res.headers.link == true && pageObject.last == true- 遞回并從 1 開始回傳 <-等待未解決的 Promise(s)
- 否則如果
res.headers.link == true && pageObject.last == false- 用
pageListResponses<- 完全解決最外面的 Promise
- 用
- 否則如果
res.headers.link == false && pageObject.last == false- 使用“未找到分頁標題”決議最外層的 Promise <- 完全解決
- 然后
then()附加到初始呼叫的方法execute()被呼叫pageListResponses- 前任。
this.execute({...}).then(pageList=>doSomethingWithPageOfResults());
- 前任。
因此,使用.then()中游的鏈接允許我們在回傳最終確定的 Promise 結果之前進行一些資料處理(正如您所做的那樣)。
在遞回代碼中:
this.execute<T>({
url: pagingObject.next,
}).then(outer);
.then()這里的呼叫只是向鏈中添加了一個新的內部 Promise,正如您所意識到的,這與撰寫完全相同:
.then(result=>outer(result)); 參考
異步/等待
最后,推薦使用Async / Await。強烈建議使用 Async/Await 重寫 Promise 代碼以處理復雜(或有人說的任何)場景。盡管仍然是異步的,但這使得代碼序列的閱讀和合理化變得更加容易。
您的代碼重寫以利用 Async/Await:
protected async execute<T>(httpOptions): Promise<T> {
const reqObject = {
...httpOptions,
baseURL: this.config.baseUri,
headers: {Authorization: `Bearer ${this.config.apiKey}`},
};
try {
const res: AxiosResponse<T> = await axios.request<T>(reqObject);
if (res) {
const pagingObject: boolean = this.getPagingObject(res);
this.pagedListResponses = this.pagedListResponses.concat(res.data);
if (pagingObject) {
return this.execute<T>({ url: 'https://jsonplaceholder.typicode.com/users/1/todos'});
} else {
return this.pagedListResponses as any;
}
} else {
return "No paging header found" as any;
}
} catch (err) {
throw new Error('Unable to complete request for data.');
}
}
在這里,async直接表示“此方法回傳一個 Promise”(按型別輸入)。該await關鍵字在代碼中僅使用一次以等待 AJAX 請求的決議。該陳述句回傳實際結果(按型別輸入),而不是 Promise 物件。網路錯誤會發生什么?注意try/catch這里的使用。該catch塊處理嵌套/鏈中的任何拒絕。您可能會注意到遞回呼叫沒有await關鍵字。在這種情況下它不是必需的,因為它是一個 Promise,它只是傳遞它的結果。(await在這里添加是可以的,但它沒有真正的好處)。
這段代碼在外面的用法也是一樣的:
this.execute({...}).then(pageList=>doSomethingWithPageOfResults());
讓我知道您可能仍然存在哪些差距。
uj5u.com熱心網友回復:
好吧,當您呼叫時this.execute,它會回傳一個Promise<AxiosResponse | T>.
因此,通過呼叫.then(outer),來自遞回execute函式的回應被用于解決您的外部承諾。
它與 基本相同this.execute(...).then(response => outer(response)),如果這樣更清楚的話。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/368251.html
標籤:javascript 打字稿 递归 es6-promise
