角度js,广播事件并等待它完成

use*_*167 3 javascript angularjs

我有一个像这样的角度事件:

$rootScope.$broadcast("postData");
doSomething();
Run Code Online (Sandbox Code Playgroud)

但是,doSomething()必须等待postData在执行之前完成.我通常会这样做:

$rootScope.$broadcast("postData").then(function(){
    doSomething();
});
Run Code Online (Sandbox Code Playgroud)

但显然这不是一个有角度的东西...任何想法?

Pra*_*ain 5

我想指出,在我们没有处理异步调用以处理回调/ promise/throw事件来解决问题的情况下,以前的解决方案是不可能实现的.异步调用可能是库函数,例如setTimeout,我们只是不能使用以前的解决方案来修复流程.

这是我的解决方案:

把doSomething(); 在setTimeout中,时间间隔设置为0,

$rootScope.$broadcast("postData");
setTimeout(function(){ 
    doSomething();}
, 0);
Run Code Online (Sandbox Code Playgroud)

就如此容易!

settimeout使dosomething()也是异步的,这使得异步操作一个接一个地发生(异步).怎么样?下面是解释,但首先请注意dosomething()的间隔为0毫秒的setTimout.显然可以认为dosomething()应该在postData事件被广播和服务之前立即执行(在0ms之后(实际上javascript中的默认最小时间间隔是4ms,因此0ms变为4ms)).

答案是不!

Settimeout不保证其中的回调函数passe必须在指定的时间间隔后执行.指定的时间间隔只是可以执行回调所需的最小时间间隔.SetTimeOut是一个异步调用.如果已经在管道中等待任何其他异步操作,则javascript首先运行它们.

要了解这一切是如何发生的,您需要了解javascript中的事件循环.

Javascript运行时是单线程的,它只有一个调用堆栈,这意味着它在编写时按顺序运行代码.那它究竟是如何实现异步性的呢?

因此,当javascript运行时遇到异步操作(如API调用,http调用,settimeout,事件广播等)时,会发生这种情况.请注意我们的本机javascipt运行时引擎(例如chromes V8引擎)中没有提供这些功能,而是由浏览器(称为webAPI)提供,它们基本上是您可以调用的线程,它们分叉独立的执行路径,与javascript运行时执行流分开,这就是实际实现并发的方式.

问题出现了Javascript运行时仍然是单线程的.那么这些webAPI如何影响运行时流程并在完成后提供结果呢?他们不能只是在完成后随时提示javascript运行时并向其提供结果吗?必须有一些机制.

所以javascript只是调用这些webAPI,而不是等待调用的输出.它只是继续并执行调用之后的代码,这就是问题中的dosomething()如何在监听和提供postDate事件之前执行.

同时,分叉线程处理http调用或setTimeout或处理事件等,无论进行异步调用.完成后,将回调推送到事件队列(任务队列)(请注意,可以将多个回调返回到此队列中).但他们不会马上跑.

javascript运行时等待调用堆栈首先变为空.当javascript运行时没有任何内容可以执行异步调用时,会逐个从任务队列中弹出回调函数并执行.

因此,实质上如果我们可以只使dosomething()异步,它将在第一次异步完成后执行.多数民众赞成我所做的.settimeout回调被推送到事件队列/任务队列.Javascript调用堆栈变空.postData事件广播的回调得到了服务.然后dosomething()有机会执行.