Javascript 多个未连接的异步事件如何等待一个承诺
我有一个系统,我需要一个来自服务器的id来处理事件。我应该只在第一个事件发生时获取id,但在那之后,我需要为每个后续事件使用相同的id。我知道如何使用async Wait等,所以我有一些类似的代码Javascript 多个未连接的异步事件如何等待一个承诺,javascript,async-await,Javascript,Async Await,我有一个系统,我需要一个来自服务器的id来处理事件。我应该只在第一个事件发生时获取id,但在那之后,我需要为每个后续事件使用相同的id。我知道如何使用async Wait等,所以我有一些类似的代码 var id = ""; async function handleEvent(e) { if (! id ) { let response = await fetch(URL) if (response.ok) { let json
var id = "";
async function handleEvent(e) {
if (! id ) {
let response = await fetch(URL)
if (response.ok) {
let json = await response.json();
id = json.id ;
}
}
// use id to handle event
}
但我的问题是,在收到响应之前,我可能会收到多个事件,因此我会收到多个重叠调用以获取新id
我怎么能有多个对handleEvent的异步调用,第一个处理获取,任何后续调用都等待它完成以访问结果?不清楚为什么您的函数被参数化为“e”。 我会用更直接的方式来写: 异步函数请求(URL){ let response=fetch(URL) if(response.ok){ 让json=wait response.json(); 返回json.id; } 返回false;
}创建一个函数,以确保使用延迟承诺只对id发出一个请求
consturl='whatever'
让idPromise//so lazy当前接受的响应依赖于一个全局变量,这并不理想。另一种选择是使用类
class-IDManager{
getId(URL){
if(this.id){
返回此.id;
}
this.id=fetch(URL)
把这个还给我
}
}
然后,当您调用getId
时,您只需等待结果。如果之前没有发出请求,将发送网络请求。如果已经有一个挂起的请求,每个调用都将等待相同的结果。如果承诺已经解决,你会立即得到结果
const idManager=new idManager();
异步函数handleEvent(){
const id=await idManager.getId(URL);
//用身份证做事。
}
这个问题的解决方案与前面的答案略有不同。我想我会发布我最终是如何做到的。来自@phil和@vaelin的答案真的帮助我解决了这个问题
这是我的解决方案
class IDManager {
async fetchID (resolve,reject ) {
const response = await fetch( URL, { } ) ;
const id = await response.json() ;
resolve( id );
}
async getID() {
if ( this.id === undefined ) {
if ( this.promise === undefined ) {
var self = this;
this.promise = new Promise( this.fetchID ).then( function(id) { self.id = id;} );
}
await this.promise;
}
return this.id;
}
}
问题是等待getID调用的获取需要几秒钟的时间。在此期间,经常有多个对getID的调用,所有这些调用都启动了另一次获取。我通过将fetch和response.json调用包装在另一个立即创建的承诺中避免了这种情况,因此避免了重复的承诺。我假设这就像某种类型的身份验证令牌?它是一个资源令牌,不是身份验证令牌,而是类似的想法。我只需要取一个。你可以用chained创建一个全局承诺。然后保证handleEvent的累积调用顺序,但你真的不应该。您真的应该使用handleEvent返回的承诺。你真正想要的是中止,不是吗?这个函数不仅仅是获取id,它还处理一个事件“e”。它需要id来处理事件。感谢@FZs,我总是忘记OPs代码中的var id
也是全局的,这取决于用例,是否将其存储在数据结构中(例如,通过url键控)是更好的选择。一个单一的、全球性的idManager
将不会有任何改进:-)@Bergi我相信这是一个理智的人可能不同意的观点。OP可以通过将其放在自己的模块中来控制对global的访问,我注意到答案现在反映了这一点。另一方面,这会降低你的灵活性。IDManager实例可以使用getter/setter控制对ID变量的访问,并且可以根据需要进行实例化。