JS 中的 api 调用是否需要等待结果?
我在一个名为 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
类中显示此信息,我必须再次等待它吗?为什么或为什么不呢?最初,我不会说不,您不会,因为您已经处理了等待/async
在 userapi.js
类中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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您需要等待它,因为使用异步关键字 ALWAYS 声明的函数会返回 Promise,即使您只在其中执行同步操作,因此您需要等待或“thenize " 它来访问它解析到的值。这取决于异步函数的实现细节,异步函数只是产生承诺的生成器。
如果您担心这个问题,因为您在同步模块中工作并且不喜欢使用异步函数来执行更多异步函数,那么有一个好消息,TOP-LEVEL wait MODULES该提案处于第 4 阶段,因此很快就会随下一个 ECMA 版本一起发布。这样,您将能够在模块内部等待,就像它们被异步函数包装一样!
https://github.com/tc39/proposal-top-level-await
You need to await it since a function declared with async keyword ALWAYS returns a Promise, even if you do only synchronous stuff inside of it, hence you need to await or "thenize" it to access the value it resolved to. That depends from the implementation details of async functions which are just generators that yield promises.
If this concerns you because you work inside sync modules and don't like to use async functions just to execute more async functions, there's a good news, TOP-LEVEL await MODULES proposal is at stage 4, so it'll very soon be shipped with the next ECMA version. This way you will be able to await inside modules as if they were wrapped by async functions !
https://github.com/tc39/proposal-top-level-await
我无法确定您是否需要再次等待它,因为我无法分辨
RECRIEVERESPONSEDATA
做什么。它可能会采用解决的价值并将其包裹在一个新的承诺中,然后需要getemployeeeinfo
等待结果的呼叫者。原因是:
诺言是围绕一个值
等待
解开承诺的包装。。然后。
就像现实世界中的礼物一样,一旦拆开了东西,您就无需再次将其解开。但是,对于我们来说非常方便的是,您仍然可以在未包装在承诺中的值上等待等待,它只会为您提供值。
您可以将任何价值包裹在承诺中,例如:
有时您最终会处于无法使用
等待
的情况下,因为您处于无法标记的async <
。 /代码>。前端框架的生命周期方法(例如React(甚至可能是VUE))就是这样:该框架需要每个生命周期方法来完成其工作并立即完成。如果将生命周期方法标记为异步,则通常可以防止其具有预期效果。在这种情况下,您通常需要使用链式
。单独的线程 - 这些都发生在执行生命周期方法的相同线程中,即浏览器的渲染器线程。但是,如果您想到执行执行的编码器,那么您 not 的承诺基本上都会将叉子引入该codepath:立即遵循一条路径,并且每当承诺解决时,请遵循另一个路径。由于Browserland几乎是一个单线程的上下文,因此认为创造一个承诺作为单独的线程并不伤害您。这是一个细微差别,您可以忽略,直到您对JS中的异步图案感到满意。
更新:
RECRIEVERESPONSEDATA
do 不似乎返回承诺。我可能是错的,如果预测
返回承诺,但是如果那是真的,那么三元级将始终返回wendesp.data
,因为未包装的承诺是真实的价值观(甚至promise.resolve(false)
是真实的)。但是,任何调用
getemployeeInfo
will 的人都必须等待它,因为该功能被标记为async
,这意味着即使没有什么,即使没有什么,它也会返回承诺内部是异步的。考虑这个极端的例子:I can't tell if you need to await it again, because I can't tell what
retrieveResponseData
does. It might take the resolved value and wrap it in a fresh promise, which would then require callers ofgetEmployeeInfo
to await the result.Here's the why:
A Promise is a wrapper around a value
await
unwraps a Promise. So does the.then()
handler you can register with a Promise (but the value is only unwrapped within the function you provide to.then()
).Just like a gift in the real world, once something has been unwrapped, you don't need to unwrap it again. However, very conveniently for us, you can still use
await
on a value that is not wrapped in a Promise, and it will just give you the value.You can wrap any value in a Promise, like so:
Sometimes you end up in a situation where you can't use
await
, because you're in a function that cannot be markedasync
. The lifecycle methods of front-end frameworks like React (and possibly Vue) are like that: the framework needs each lifecycle method to do its job and be done immediately. If you mark the lifecycle method as async, you can often prevent it from having the intended effect.In cases like that, you often need to use chained
.then()
handlers, which is a little uglier, but it works: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, ifpredict
returns a Promise, but if that were true, then the ternary would always returnresponse.data
because unwrapped Promises are truthy values (evenPromise.resolve(false)
is truthy).However, anyone who calls
getEmployeeInfo
will have to wait it, because that function is markedasync
, and that means it returns a Promise even if nothing inside it is is asynchronous. Consider this extreme example:async函数
getemployeeInfo
等待get
调用的结果,以返回呼叫返回的值RECRIEVERESPONESPONESPONEDATATA
。假设
get
也不是reacrieveresponEdata
错误,则使用geteMployeeeeInfo
的句法返回的值返回的值,用于解决通过调用getEmployeeInfo 。
Promise.resolve
不需要将调用getEmployeeeInfo
转换为承诺的结果,因为给定的异步函数返回返回承诺。reacrieveresponsedata
是否返回承诺并不重要:标准async函数处理等待在调用异步函数时返回的承诺返回的承诺之前,请等待返回的承诺值。异步函数
setrReportData
被声明为async
,但使用链接的承诺处理程序方法编写以处理数据和错误条件的顺序 - 可以省略异步声明,但如果修改,则可能有用制作。完成和提取的时候更新页面
结果只能在获得数据 数据可用。插入更新页面的最简单的位置(在已发布的代码中)在
然后在
处理程序> setReportdata 内的处理程序函数中。显示数据
已发布
setReportData
不会通过回调或通过返回承诺来通知其呼叫者。它所做的就是将结果保存在this.reportDataTableEmployeeEinfo
和DIES中。在不使用回调的情况下,
setReportData
将带有两个选择返回承诺,例如
Resulte EmployeeeeeInfo
或Undefined
如果一个错误发生:可以使用类似于
的承诺在呼叫序列中使用的
如果您想在异步上下文中拨打电话,则可以使用
等待
:在数据可用后,从
setReportdata
内部更新页面(如该数据可用时,如图所示,在此的第一部分中显示为注释回答)。该方法可能应从setReportData
重命名为getReportData
或类似以反映其目的。Async function
getEmployeeInfo
awaits the result of theget
call in order to return the value returned by a call toretrieveResponeData
.Assuming neither
get
norretrieveResponeData
errors, the value syntactically returned in the body ofgetEmployeeInfo
is used to resolve the promise object actually returned by callinggetEmployeeInfo
.Promise.resolve
is not needed to convert the result of callinggetEmployeeInfo
into a promise because, given async functions return promises, it already is.It doesn't matter if
retrieveResponseData
returns a promise or not: standard async function processing waits for a returned promise value to be settled before resolving the promise returned when calling the async function.Async function
setRreportData
is declared asasync
but written using chained promise handler methods to process data and error conditions in order - the async declaration could be omitted, but may be useful if modifications are made.The results can only be used to update the page at a time when the data has finished being obtained and extracted, shown as a comment in the following code:
Displaying the data using
EmployeeView.vue class
must wait until the data is available. The simplest place to insert updating the page (in the posted code) is within thethen
handler function insidesetReportData
.Displaying the data
As posted
setReportData
does not notify its caller of when report data is available, either by means of a callback or by returning a promise. All it does is save the result inthis.reportDatatableEmployeeInfo
and dies.Without using callbacks,
setReportData
is left with two choicesReturn a promise that is fulfilled with, say,
resultsEmployeeInfo
orundefined
if an error occurs:which could be used in a calling sequence using promises similar to
If you wanted to make the call in an async context you could use
await
:Update the page from within
setReportData
after the data becomes available ( as shown as a comment in the first part of this answer). The method should probably be renamed fromsetReportData
togetReportData
or similar to reflect its purpose.