涉及异步调用时,如何设置特定的执行顺序? [英] How do I set a specific order of execution when asynchronous calls are involved?

查看:285
本文介绍了涉及异步调用时,如何设置特定的执行顺序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是JavaScript领域的新手(两天!!),我唯一的编码经验是在Java中按顺序执行语句. 我了解或至少已经读过JavaScript是异步的,这意味着如果有一条语句需要花费很长的时间才能执行,则下一条语句将在不保留第一条语句的程序的情况下执行. 我遇到了回调(实际上很多!),但是我看不到如何将它们用于确定执行顺序.我写了一段代码只是为了了解它是如何完成的,而且我肯定可以使用一些帮助.

I am new(2 days!!) to the world of JavaScript and my only prior coding experience is in Java where execution of statements takes place sequentially. I understand that or at least I've read that JavaScript is asynchronous which means that if there is a statement that takes a long time to execute, the next statement is executed without holding up the program for the first statement. I came across callbacks(a lot actually!!) but I couldn't see how they could be used to determine the order of execution. I wrote a piece of code just to understand how it could be done and I sure could use some help.

console.log("Beginning");

function Test(callback){
   setTimeout(function(callback){
       console.log("Something that takes a lot of time");
   },5000);
   callback();
}

function tstCallBack(){
    console.log("Should come last");
}

Test(tstCallBack);

我想要的是显示输出-

Beginning
Something that takes a lot of time
Should come last

但是我得到的输出是-

Beginning
Should come last
Something that takes a lot of time

我能做些什么来获得想要的输出结果吗?

Is there anything I can do to get the output in the way I want it?

推荐答案

让我们澄清一下您所说的内容:

Let's clear some things up in what you said:

我是JavaScript世界的新手(仅2天!),并且是我之前唯一的编码 Java的经验是执行语句 按顺序.我了解,或者至少我已经阅读过JavaScript 是异步的,这意味着如果有一条语句需要一个 执行时间长,下一条语句执行不需保持 调出程序的第一条语句.

I am new(2 days!!) to the world of JavaScript and my only prior coding experience is in Java where execution of statements takes place sequentially. I understand that or at least I've read that JavaScript is asynchronous which means that if there is a statement that takes a long time to execute, the next statement is executed without holding up the program for the first statement.

这不是它的工作方式.给定功能在设计上可以是异步的,也可以是同步的.它与执行所需的时间绝对无关.您可以具有非常快速的异步功能或非常长的同步功能.确定功能是否异步的是它的设计方式.如果它使用异步I/O或计时器或任何其他异步基础结构,则该函数的至少某些执行是异步的.这意味着某些函数将在稍后完成,而某些代码将在异步调用完成之前在此函数调用之后立即执行.

This is not how it works. A given function is either asynchronous or its synchronous by design. It has absolutely nothing to do with how long it takes to execute. You can have a very quick async function or a very long synchronous function. What determines whether the function is asynchronous or not is how it is designed. If it uses async I/O or timers or any other async infrastructure, then at least some of the execution of the function is asynchronous. That means that some of the function will finish LATER and some of the code right after this function call will execute BEFORE the async portion finishes.

我遇到了回调(实际上很多!),但是我看不到它们如何 可用于确定执行顺序.我写了一篇 代码只是为了了解如何实现,我肯定可以使用一些 帮助.

I came across callbacks(a lot actually!!) but I couldn't see how they could be used to determine the order of execution. I wrote a piece of code just to understand how it could be done and I sure could use some help.

回调用于在某些异步操作完成后通知调用代码.它既可以用于消耗异步操作的结果,也可以用于执行要在异步操作完成后按顺序运行的下一段代码.

Callbacks are used to notify the calling code when some asynchronous operation has completed. This can be used either to consume the result of the asynchronous operation or can be used to execute the next piece of code that wants to run in sequence after the async operation has finished.

在代码示例中,如果需要所需的序列,则必须在setTimeout()回调内部调用该回调,以便在执行setTimeout()之后它被调用,从而为您提供所需的序列.

In your code example, if you want the desired sequence, then you must call the callback inside the setTimeout() callback so that it gets called AFTER the setTimeout() called executes, thus giving you the desired sequence.

您还必须删除setTimeout回调的callback参数.该回调未随该参数传递,因此将其声明为错误.可以通过闭包直接从父函数访问它,如下所示:

You also have to remove the callback argument to the setTimeout callback. That callback is not passed with that argument so declaring it there is just wrong. It can be accessed directly from the parent function via a closure as shown here:

console.log("Beginning");

function Test(callback){
   setTimeout(function(){
       console.log("Something that is asynchronous");
       // call the callback here to indicate to the calling code
       // that the asynchronous operation is now complete
       callback();
   },5000);
   console.log("After Setting Timer");
}

function tstCallBack(){
    console.log("Should come last");
}

Test(tstCallBack);

这将在以下控制台中生成一个序列:

This will generate a sequence in the console of:

开始

设置计时器后

异步的东西

应该倒数


从概念上讲,JavaScript引擎运行一个线程,并且该线程使用事件队列.因此,在上面的函数中,会发生这种情况.


Conceptually, the Javascript engine runs a single thread and that single thread uses an event queue. So, in your function above, this is what happens.

  1. 第一个console.log("Beginning");被执行.
  2. Test(tstCallback)被调用.
  3. 作为执行Test()功能的一部分,计划了一个计时器.这会在JS引擎内部注册一个计时器.
  4. 继续执行Test()中的代码,执行console.log("After Setting Timer");,然后该函数结束.
  5. 当前JS执行线程完成,并且如果事件队列中没有其他内容,则JS引擎无需执行任何操作,而是等待下一个事件发生.
  6. 稍后(设置计时器的5秒),内部计时器将触发,并将计时器事件放入JS事件队列中.
  7. 由于目前没有其他JS在执行,因此将计时器事件从事件队列中拉出并执行.这意味着将调用为计时器注册的原始回调.
  8. 在调用计时器回调时,它将执行console.log("Something that is asynchronous");行,然后调用callback().
  9. 然后调用您的tstCallback函数并执行console.log("Should come last");.
  10. 异步事件完成执行,并且JS引擎查看事件队列中是否还有其他事件.如果是这样,则将下一个事件从队列中拉出并运行.
  1. The first console.log("Beginning"); is executed.
  2. Test(tstCallback) is called.
  3. As part of executing the Test() function, a timer is scheduled. This registers a timer internal to the JS engine.
  4. The execution of code in Test() continues, console.log("After Setting Timer"); is executed and then that function finishes.
  5. The current thread of JS execution finishes and if there is nothing else in the event queue, then the JS engine has nothing to do, but wait for the next event to occur.
  6. Some time later (the 5 seconds that your timer is set for), the internal timer fires and it puts the timer event in the JS event queue.
  7. Since there is no other JS executing at the moment, the timer event is pulled out of the event queue and executed. This means that the original callback that was registered for the timer is called.
  8. As the timer callback is called, it executes the console.log("Something that is asynchronous"); line and then calls callback().
  9. Your tstCallback function is then called and console.log("Should come last"); is executed.
  10. The async event finishes execution and the JS engine looks to see if there are any more events in the event queue. If so, the next event is pulled out of the queue and it is run.


关于Javascript如何处理异步操作,有很多很好的参考文献:


There are a number of very good references on how Javascript handles asynchronous operations:

JavaScript如何处理背景?

JavaScript计时器的工作原理

做我需要关注异步Java的竞争条件吗?

这篇关于涉及异步调用时,如何设置特定的执行顺序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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