我还有一个不同的同步函数需要检索值 – 最好是从缓存中检索,如果它是缓存未命中,那么从数据源开始
(我意识到以同步方式进行IO操作是不明智的,但我们假设在这种情况下需要这样做).
我的问题是我希望同步函数能够等待来自异步函数的值,但是不可能在非异步函数中使用await关键字:
function syncFunc(key) { if (!(key in cache)) { await updateCacheForKey([key]); } } async function updateCacheForKey(keys) { // updates cache for given keys ... }
现在,通过将updateCacheForKey中的逻辑提取到新的同步函数中,并从现有函数中调用此新函数,可以轻松避免这种情况.
我的问题是为什么首先绝对防止这个用例?我唯一的猜测是它与“白痴防范”有关,因为在大多数情况下,从同步函数等待异步函数是错误的.但我认为它有时会有其有效的用例我错了吗?
(我认为这也可以通过使用Task.Wait在C#中实现,尽管我可能会在这里混淆一些事情).
解决方法
My problem is I’d like the synchronous function to be able to wait for a value from the async one…
他们不能,因为:
> JavaScript基于由线程处理的“作业队列”工作,其中作业具有运行到完成语义,并且
> JavaScript实际上并没有异步功能(真的 – 坚持这个……)
作业队列(事件循环)在概念上非常简单:当需要完成某些事情(脚本的初始执行,事件处理程序回调等)时,该工作将被放入作业队列中.为该作业队列提供服务的线程获取下一个待处理作业,将其运行至完成,然后返回下一个作业. (当然,它比这更复杂,但这足以满足我们的目的.)因此,当一个函数被调用时,它被调用作为处理作业的一部分,并且作业总是在下一个作业运行之前处理完成.
运行完成意味着如果作业调用了一个函数,那么该函数必须在作业完成之前返回.当线程运行以执行其他操作时,作业不会在中间暂停.这使得代码变得非常简单,可以正确地编写和推理,而不是在其他事情发生时,作业可能会被暂停. (再次它比这更复杂,但这又足以满足我们的目的.)
到现在为止还挺好.这有什么关于没有真正拥有异步功能的东西?!
虽然我们谈论“同步”和“异步”函数,甚至有一个async关键字我们可以应用于函数,但函数调用在JavaScript中始终是同步的.异步函数并不存在.我们有同步函数可以设置环境稍后会调用的回调(通过排队作业).
我们假设updateCacheForKey看起来像这样:
async function updateCacheForKey(key) { const value = await fetch(/*...*/); cache[key] = value; return value; }
在幕后,真正做的是:
function updateCacheForKey(key) { return fetch(/*...*/).then(result => { const value = result; cache[key] = value; return value; }); }
它要求浏览器启动获取数据的过程,并向其注册回调(通过那时),以便浏览器在数据返回时调用,然后退出,从此返回promise.尚未获取数据,但updateCacheForKey已完成.它已经回来了.它同步完成了它的工作.
稍后,当提取完成时,浏览器会将作业排队以调用该保证回调;当从队列中获取该作业时,将调用回调,并且其返回值用于解析随后返回的promise.
My question is why absolutely prevent this use case in the first place?
让我们看看它会是什么样子:
>线程获取一个作业,该作业涉及调用syncFunc,它调用updateCacheForKey. updateCacheForKey要求浏览器获取资源并返回其promise.通过这种非异步等待的魔力,我们同步等待该承诺得到解决,从而阻止了这项工作.
>在某些时候,浏览器的网络代码完成检索资源并对作业进行排队,以调用我们在updateCacheForKey中注册的promise回调.
>再也没有发生过. 原文链接:https://www.f2er.com/js/158338.html