Fra*_*tti 17 javascript blocking
我有一个有趣的情况,我通常聪明的头脑无法提出解决方案:)这是情况......
我有一个有get()方法的类...这个方法被调用来获取存储的用户首选项......它所做的是调用某个底层提供程序来实际获取数据...现在写入,它正在调用会话cookie的提供者...所以,get()调用providerGet()让我们说,providerGet()返回一个值,get()将它传递给调用者.调用者希望在它继续工作之前做出响应.
这是棘手的部分...我现在正在尝试实现一个异步的提供程序(在这种情况下使用本地存储)...所以,providerGet()将立即返回,已经调度到本地存储将调用,一段时间之后,调用一个传递给它的回调函数...但是,由于providerGet()已经返回,所以get()现在通过扩展到原来的被调用,它显然没有返回实际检索的数据.
那么,问题是,是否有一种方法可以基本上"阻止"从providerGet()返回,直到异步调用返回?请注意,出于我的目的,我并不关心这可能带来的性能影响,我只想弄清楚如何使其工作.
我不认为有办法,当然我知道我无法想出来...所以我想把它扔掉,看看其他人能想出来:)
编辑:我现在只是在学习问题的核心,即web sql API是非同步的这一事实,可能有一个解决方案...原来还有一个API的同步版本,我没有意识到...我现在正在阅读文档以了解如何使用它,但这可以很好地解决问题,因为providerGet()完全异步编写的唯一原因是允许该提供程序...获取的代码( )是我自己的抽象层的一部分,在各种存储提供商(cookies,web sql,localStorage等)之上,所以最低的共同点必须赢,这意味着如果一个是同步的,他们都必须是非同步的......唯一的一个是web sql ...所以如果有一种方法可以同步地做到这一点我的观点变得没有实际意义(尽管我认为仍然是一个有趣的问题)
edit2:好吧,似乎没有任何帮助......似乎API的同步版本没有在任何浏览器中实现,即使它是指定它只能从工作线程使用,所以这不无论如何它似乎都有所帮助.虽然,读一些其他的东西,听起来有一种方法来使用递归来拉动这个技巧...我现在正在抛出一些测试代码,如果/当我让它工作时我会发布它,看起来像一个非常有趣的一般地解决任何这种情况的方法.
编辑3:根据我下面的评论,我真的没办法完全按照自己的意愿行事.我要解决我当前问题的解决方案是不允许使用Web SQL进行数据存储.它不是理想的解决方案,但是由于该规范不断变化而且没有广泛实施,它不是世界末日......希望当它得到适当的支持时,同步版本将可用,我可以插入新的提供商,很高兴去.一般来说,似乎没有任何方式可以拉动这个奇迹...确认我的预期是这样的,但希望我错了这一次:)
goa*_*oat 14
产生一个webworker线程来为你做异步操作.传递它需要执行任务加上唯一ID的信息.诀窍是让它在结束时将结果发送到网络服务器.
同时......产生webworker的函数向同一个webserver发送一个ajax请求,使用xmlhttprequest对象的同步标志(是的,它有一个同步选项).因为它将阻止直到http请求完成,你可以让你的webserver脚本轮询数据库以获取更新或其他任何内容,直到结果发送给它.
丑陋,我知道.但它会阻塞而不会占用cpu:D
基本上
function get(...) {
spawnWebworker(...);
var xhr = sendSynchronousXHR(...);
return xhr.responseTEXT;
}
Run Code Online (Sandbox Code Playgroud)
不,在异步调用完成之前,您无法阻止.就这么简单.
听起来你可能已经知道这一点,但如果你想使用异步ajax调用,那么你必须重新调整代码的使用方式.你不能只有一个.get()方法来进行异步ajax调用,阻塞直到它完成并返回结果.在这些情况下最常用的设计模式(例如,查看所有进行网络连接的Google的javascript API)是让调用者为您传递完成功能.调用.get()将启动异步操作,然后立即返回.操作完成后,将调用完成功能.调用者必须相应地构造其代码.
在使用异步网络时,您根本无法编写直接的,顺序的过程javascript代码,如:
var result = abc.get()
document.write(result);
Run Code Online (Sandbox Code Playgroud)
最常见的设计模式是这样的:
abc.get(function(result) {
document.write(result);
});
Run Code Online (Sandbox Code Playgroud)
如果你的问题是几个深层调用层,那么回调可以传递到不同的级别并在需要时调用.