我在一個名為的類中有以下端點UserApi.js:
const controller = 'User';
...
export async function getEmployeeInfo(employeeId)
{
const query = createQueryFromObject({employeId});
const response = await get(`/${controller}/EmployeeInfo?${query}`);
return retrieveResponseData(response, []);
}
這將從UserController.cs.
現在,說我想在EmployeeView.vue課堂上顯示這個資訊,我是不是又要 await 了?為什么或者為什么不?最初,我會說不,你不會,因為你已經await/async在UserApi.js課堂上處理過,但是Promise.resolve呢?請解釋。
methods: {
async setReportData(
employeeId
) {
this.isBusy = true;
Promise.resolve(getEmployeeInfo(
employeeId
)).then((resultsEmployeeInfo) => {
this.reportDatatableEmployeeInfo = resultsEmployeeInfo;
})
.catch(() => {
this.alerts.error('An error has occurred while fetching the data');
})
.finally(() => {
this.isBusy = false;
});
},
更新: ....
* @param {Object} response
* @param {any} defaultData
* @param {Function} predicate
* @returns {Promise}
*/
export function retrieveResponseData(response, defaultData = null, predicate = (predicateResponse) => predicateResponse) {
const data = predicate(response) ? response.data : null;
return data || defaultData;
}
uj5u.com熱心網友回復:
您需要等待它,因為使用 async 關鍵字宣告的函式總是回傳一個 Promise,即使您只在其中執行同步操作,因此您需要等待或“然后化”它以訪問它決議為的值。這取決于異步函式的實作細節,這些函式只是 產生承諾的生成器。
如果你因為在同步模塊中作業而擔心你,并且不喜歡使用異步函式來執行更多異步函式,那么有一個好訊息,TOP-LEVEL await MODULES提案處于第 4 階段,所以它很快就會發布下一個 ECMA 版本。這樣你就可以在模塊內部等待,就好像它們被異步函式包裝了一樣! https://github.com/tc39/proposal-top-level-await
uj5u.com熱心網友回復:
我不知道您是否需要再次等待它,因為我不知道是什么retrieveResponseData。它可能會采用已解決的值并將其包裝在一個新的 Promise 中,然后要求呼叫者getEmployeeInfo等待結果。
原因如下:
Promise 是一個值的包裝器
await解開一個 Promise。您可以使用 Promise 注冊的處理程式也是如此.then()(但該值僅在您提供給的函式中展開.then())。
就像現實世界中的禮物一樣,一旦打開包裝,您就無需再次打開包裝。但是,對我們來說非常方便的是,您仍然可以使用await未包裝在 Promise 中的值,它只會為您提供值。
您可以將任何值包裝在 Promise 中,如下所示:
let wrappedFive = Promise.resolve(5)
//> wrappedFive is a Promise that must be unwrapped to access the 5 inside it
// this does _exactly_ the same thing as the above
let wrappedFive = new Promise(resolve => {
resolve(5)
})
有時您最終會遇到無法使用的情況await,因為您處于無法標記的功能中async。像 React(可能還有 Vue)這樣的前端框架的生命周期方法是這樣的:框架需要每個生命周期方法來完成它的作業并立即完成。如果將生命周期方法標記為異步,通常會阻止它產生預期效果。
在這種情況下,您通常需要使用鏈式.then()處理程式,這有點難看,但它確實有效:
componentDidMount() {
// this API call is triggered immediately by lifecycle,
// but it basically starts a separate thread -- the rest
// of this function does not wait for the call to finish
API.getUserInfo()
.then(userInfo => {
// this happens after the API call finishes, but
// componentDidMount has already finished, so what happens
// in here cannot affect that function
this.setState({ username: userInfo.username })
})
// this happens immediately after the API call is triggered,
// even if the call takes 30 seconds
return 5
}
Note that a Promise does not actually start a separate thread -- these all happen in the same thread that executes the lifecycle method, i.e. the browser's renderer thread. But if you think of the codepath that executes, a Promise that you don't wait for basically introduces a fork into that codepath: one path is followed immediately, and the other path is followed whenever the Promise resolves. Since browserland is pretty much a single-threaded context, it doesn't really hurt you to think of creating a Promise as spawning a separate thread. This is a nuance you can ignore until you are comfortable with asychronous patterns in JS.
Update: retrieveResponseData does not appear to return a Promise. I could be wrong, if predict returns a Promise, but if that were true, then the ternary would always return response.data because unwrapped Promises are truthy values (even Promise.resolve(false) is truthy).
However, anyone who calls getEmployeeInfo will have to wait it, because that function is marked async, and that means it returns a Promise even if nothing inside it is is asynchronous. Consider this extreme example:
// this function returns a number
function gimmeFive() {
return 5
}
// this function returns a Promise wrapped around a number
async function gimmeFive() {
return 5
}
uj5u.com熱心網友回復:
異步函式getEmployeeInfo等待get呼叫的結果,以便回傳呼叫回傳的值retrieveResponeData。
假設既get沒有錯誤也沒有retrieveResponeData錯誤,在語法上回傳的值getEmployeeInfo用于決議呼叫實際回傳的 Promise 物件 getEmployeeInfo。
Promise.resolve不需要將呼叫結果轉換getEmployeeInfo為 Promise,因為給定異步函式回傳 Promise,它已經是。
是否回傳 Promise 無關緊要retrieveResponseData:標準異步函式處理等待回傳的 Promise 值解決,然后再決議呼叫異步函式時回傳的 Promise。
異步函式setRreportData被宣告為async但使用鏈式 promise 處理程式方法撰寫,以按順序處理資料和錯誤條件 - 異步宣告可以省略,但如果進行修改可能會很有用。
結果只能在資料獲取和提取完成時用于更新頁面,在以下代碼中顯示為注釋:
setReportData( employeeId) {
this.isBusy = true;
getEmployeeInfo(
employeeId
).then((resultsEmployeeInfo) => {
this.reportDatatableEmployeeInfo = resultsEmployeeInfo;
// At this point the result in this.reportDatatableEmployeeInfo can be used to update the page
})
.catch(() => {
this.alerts.error('An error has occurred while fetching the data');
})
.finally(() => {
this.isBusy = false;
});
},
使用顯示資料EmployeeView.vue class必須等到資料可用。插入更新頁面(在發布的代碼中)的最簡單位置是then在setReportData.
顯示資料
正如所發布setReportData的那樣,不會通過回呼或回傳承諾通知其呼叫者何時報告資料可用。它所做的只是將結果保存this.reportDatatableEmployeeInfo并死亡。
不使用回呼,setReportData有兩個選擇
回傳一個被履行的承諾,比如說,
resultsEmployeeInfo或者undefined如果發生錯誤:setReportData( employeeId) { this.isBusy = true; // return the final promise: return getEmployeeInfo( employeeId ) .then( (resultsEmployeeInfo) => (this.reportDatatableEmployeeInfo = resultsEmployeeInfo) ) .catch(() => { this.alerts.error('An error has occurred while fetching the data'); // return undefined }) .finally(() => { this.isBusy = false; }); },可以在呼叫序列中使用類似于
if(!this.busy) { this.setReportData(someId).then( data => { if( data) { // update page } }If you wanted to make the call in an async context you could use
await:if(!this.busy) { const data = await this.setReportData(someId); if( data) { // update page } }Update the page from within
setReportDataafter the data becomes available ( as shown as a comment in the first part of this answer). The method should probably be renamed fromsetReportDatatogetReportDataor similar to reflect its purpose.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/457848.html
標籤:javascript api Vue.js 异步等待 承诺
