如何调用异步JavaScript函数并阻止原始调用者 [英] How to call an asynchronous JavaScript function and block the original caller

查看:87
本文介绍了如何调用异步JavaScript函数并阻止原始调用者的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个有趣的情况,我通常聪明的想法无法为:)解决方案:

I have an interesting situation that my usually clever mind hasn't been able to come up with a solution for :) Here's the situation...

我有一个具有get()方法的类...调用该方法以获取存储的用户首选项...它的作用是调用某些基础提供程序以实际获取数据...如现在所述,它正在调用谈论cookie的提供程序...因此,get()调用providerGet()可以说,providerGet()返回一个值,并将get()传递给调用者.呼叫者在明显继续其工作之前会期望得到响应.

I have a class that has a get() method... this method is called to get stored user preferences... what it does is calls on some underlying provider to actually get the data... as written now, it's calling on a provider that talks cookies... so, get() calls providerGet() let's say, providerGet() returns a value and get() passes it along to the caller. The caller expects a response before it continues its work obviously.

这是棘手的部分...我现在正在尝试实现一个本质上不同步的提供程序(在这种情况下使用本地存储)...因此,providerGet()将立即返回,并已调度了对本地的调用存储将在一段时间后调用传递给它的回调函数...但是,由于providerGet()已经返回,并且get()现在也扩展了原来的调用,因此显然没有返回实际检索到的数据.

Here's the tricky part... I now am trying to implement a provider that is asychronous in nature (using local storage in this case)... so, providerGet() would return right away, having dispatched a call to local storage that will, some time later, call a callback function that was passed to it... but, since providerGet() already returned, and so did get() now by extension to the original called, it obviously hasn't returned the actual retrieved data.

所以,问题是,有没有一种方法可以实质上阻止" providerGet()的返回,直到异步调用返回为止?请注意,出于我的目的,我并不担心这种性能可能带来的影响,我只是想弄清楚如何使其发挥作用.

So, the question is simply is there a way to essentially "block" the return from providerGet() until the asychronous call returns? Note that for my purposes I'm not concerned with the performance implications this might have, I'm just trying to figure out how to make it work.

我不认为有办法,当然我知道我还没有想出办法...所以我想把它扔出去,看看其他人能想出什么办法:)

I don't think there's a way, certainly I know I haven't been able to come up with it... so I wanted to toss it out and see what other people can come up with :)

edit:我现在才知道问题的核心,即Web sql API不同步,这一事实可能有解决方案……事实证明,该API也有一个同步版本,我没有做过没意识到...我现在正在阅读文档以了解如何使用它,但这可以很好地解决该问题,因为providerGet()完全不同步地编写的唯一原因是允许该provider ...代码get()的一部分是我自己的抽象层,位于各种存储提供程序(Cookie,Web sql,localStorage等)之上,因此必须赢得最低的公分母,这意味着如果一个人不同步,则它们都必须是不同步的. .唯一的一个是Web sql ...因此,如果有一种方法可以做到这一点,我的观点将变得毫无意义(尽管我还是认为这是一个有趣的问题)

edit: I'm just learning now that the core of the problem, the fact that the web sql API is asychronous, may have a solution... turns out there's a synchronous version of the API as well, something I didn't realize... I'm reading through docs now to see how to use it, but that would solve the problem nicely since the only reason providerGet() was written asychronously at all was to allow for that provider... the code that get() is a part of is my own abstraction layer above various storage providers (cookies, web sql, localStorage, etc) so the lowest common denominator has to win, which means if one is asychronous they ALL have to be asychronous... the only one that was is web sql... so if there's a way to do that synchronously my point become moot (still an interesting question generically I think though)

edit2:嗯,似乎没有任何帮助……似乎该API的同步版本未在任何浏览器中实现,即使已指定它只能在辅助线程中使用,所以这无论如何似乎都不会有帮助.虽然,阅读其他内容听起来好像可以使用递归来解决这个问题……我现在把一些测试代码放到一起,如果/当我能正常工作的时候,我会把它发布出来,这似乎很有趣解决这种情况的方法.

edit2: Ah well, no help there it seems... seems like the synchronous version of the API isn't implemented in any browser and even if it was it's specified that it can only be used from worker threads, so this doesn't seem like it'd help anyway. Although, reading some other things it sounds like there's a way to pull of this trick using recursion... I'm throwing together some test code now, I'll post it if/when I get it working, seems like a very interesting way to get around any such situation generically.

edit3:根据我在下面的评论,确实没有办法完全按照我的意愿去做.我要解决的当前问题的解决方案是完全不允许使用Web SQL进行数据存储.这不是理想的解决方案,但是由于该规范在不断变化并且并未得到广泛实施,因此它还不是世界末日...希望当它得到适当支持的同步版本出现时,我可以为此插入一个新的提供程序,并且很好走.一般来说,似乎没有任何办法可以拉开这个奇迹……证实了我的期望,但是希望我这次错了:)

edit3: As per my comments below, there's really no way to do exactly what I wanted. The solution I'm going with to solve my immediate problem is to simply not allow usage of web SQL for data storage. It's not the ideal solution, but as that spec is in flux and not widely implemented anyway it's not the end of the world... hopefully when its properly supported the synchronous version will be available and I can plug in a new provider for it and be good to go. Generically though, there doesn't appear to be any way to pull of this miracle... confirms what I expected was the case, but wish I was wrong this one time :)

推荐答案

不,您只能在调用结束之前才能阻止.就这么简单.

No, you can't block until the asynch call finishes. It's that simple.

听起来您可能已经知道这一点,但是如果您要使用异步ajax调用,则必须重新构造代码的使用方式.您不能只拥有.get()方法来进行异步ajax调用,直到完成并阻塞并返回结果.在这些情况下,最常用的设计模式(例如,查看所有用于联网的Google javascript API)是使调用方向您传递完成功能.调用.get()将启动异步操作,然后立即返回.操作完成后,将调用完成功能.调用者必须相应地构造其代码.

It sounds like you may already know this, but if you want to use asynchronous ajax calls, then you have to restructure the way your code is used. You cannot just have a .get() method that makes an asynchronous ajax call, blocks until it's complete and returns the result. The design pattern most commonly used in these cases (look at all of Google's javascript APIs that do networking, for example) is to have the caller pass you a completion function. The call to .get() will start the asynchronous operation and then return immediately. When the operation completes, the completion function will be called. The caller must structure their code accordingly.

使用异步网络时,您根本无法编写直接的,顺序的过程式javascript代码:

You simply cannot write straight, sequential procedural javascript code when using asynchronous networking like:

var result = abc.get()
document.write(result);

最常见的设计模式是这样的:

The most common design pattern is like this:

abc.get(function(result) {
    document.write(result);
});

如果您的问题涉及多个调用层,则可以将回调传递到不同的级别并在需要时调用.

If your problem is several calling layers deep, then callbacks can be passed along to different levels and invoked when needed.

仅供参考,较新的浏览器支持promise的概念,然后可以将它们与asyncawait一起使用以编写看起来像这样的代码:

FYI, newer browsers support the concept of promises which can then be used with async and await to write code that might look like this:

async function someFunc() {
    let result = await abc.get()
    document.write(result);
}

这仍然是异步的.它仍然是非阻塞的. abc.get()必须返回解析为值result的promise.该代码必须在声明为async的函数内部,并且该函数之外的其他代码将继续运行(这就是这种非阻塞性的原因).但是,当您编写的代码位于其所包含的特定功能本地时,您就可以编写看起来更像是阻塞代码的代码.

This is still asynchronous. It is still non-blocking. abc.get() must return a promise that resolves to the value result. This code must be inside a function that is declared async and other code outside this function will continue to run (that's what makes this non-blocking). But, you get to write code that "looks" more like blocking code when local to the specific function it's contained within.

这篇关于如何调用异步JavaScript函数并阻止原始调用者的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆