2015-05-28 25 views
0

我是新的(2天!!)JavaScript的世界,我唯一的编码经验是Java语言执行顺序发生。 我明白,或者至少我已经读过JavaScript是异步的,这意味着如果有一个语句需要很长时间才能执行,那么执行下一条语句时不会阻止第一条语句的程序。 我遇到过回调(其实很多!!),但我看不出它们如何被用来确定执行顺序。我写了一段代码只是为了了解它是如何完成的,我当然可以使用一些帮助。如何在涉及异步调用时设置执行的特定顺序?

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 

有什么我可以做的就是在输出我想要的方式?

+0

“JavaScript是异步的,这意味着如果有一个声明需要很长时间才能完成xecute,下一个语句执行时不会阻止第一个语句的程序。“这是错误的,javascript的异步陈述是真实的,但这不是因为一个函数需要很长时间,线程会自动进一步跳转,这取决于它是否是异步函数。 Btw Java在最近的版本中可以是异步的,但它不太常见。 –

+0

@NexusDuck - 非常感谢你!这是我错过的。也就是说(如果我错了,纠正我),JavaScript具有这些内置功能,这些功能很容易导致/或者导致延迟,并且这些功能是异步的以避免问题;这意味着我们无法自定义制作我们自己的异步函数(不依赖于内置的东西) 我是对的吗? – Savvy

+0

你是对的,看看@ jfriend00的回答,他有一个更详细的版本(重要的一点是,JavaScript具有更异步的本质,因为它是单线程的,而Java可以是多线程的) –

回答

2

让我们澄清一些事情你所说:

我是新(2天!)到JavaScript和我唯一的现有技术的编码 经验的世界是在Java中,语句的执行发生 。我明白,或者至少我读过,JavaScript 是异步的,这意味着如果有一条语句需要很长时间才能执行,则执行下一条语句时不会将第一条语句的程序保存为 。

这不是它的工作原理。给定的函数可以是异步的,也可以是按设计同步的。它与执行需要多长时间完全没有关系。您可以拥有非常快速的异步功能或非常长的同步功能。什么决定了函数是否是异步的是它的设计。如果它使用异步I/O或定时器或任何其他异步基础架构,那么至少某些函数的执行是异步的。这意味着一些函数将在完成后执行,并且在该函数调用之后的一些代码将在异步部分完成之前执行。

我遇到了回调(其实很多!!),但我看不到他们如何使用 来确定执行顺序。我写了一段 代码只是为了了解它是如何完成的,我肯定可以使用一些 的帮助。

回调函数用于在某些异步操作完成时通知调用代码。这可以用来消耗异步操作的结果,也可以用来执行下一段想要在异步操作完成后依次运行的代码。

在你的代码示例中,如果你想要所需的序列,那么你必须调用setTimeout()回调中的回调,以便在setTimeout()调用执行后被调用,从而为您提供所需的序列。

您还必须将callback参数移除到setTimeout回调。该回调没有通过该参数传递,因此声明它是错误的。它可以直接从通过关闭父功能如下所示进行访问:

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); 

这将产生的控制台序列:

开始

设置定时器

异步的东西

应该最后一次


概念,JavaScript引擎运行的单个线程和单线程使用事件队列。所以,在你上面的函数中,这是发生了什么。

  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引擎查看事件队列中是否有更多事件。如果是这样,则将下一个事件从队列中拉出并运行。

有JavaScript的如何处理异步操作的数量非常好的参考:

How does JavaScript handle AJAX responses in the background?

How Javascript Timers Work

Do I need to be concerned with race conditions with asynchronous Javascript?

+0

虽然没有必要把回调作为setTimeout的函数的参数,但它可以在函数内由于关闭而访问 –

+0

@NexusDuck - 你是对的,我修好了。 – jfriend00

+0

@ jfriend00 - 我终于明白了...谢谢你sooo !!你从很多苦难中拯救了我,希望我有了代表upvote .. – Savvy

0

广场内setTimeout回调,而不是外界称为callback将第一的setTimeout之前执行不作为的JavaScript不会等待setTimeout执行(as JS is synchronous by nature)和执行的下一行,因此你不会得到期望的输出。

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

Demo

1

很多你所说的话是错误的。 JavaScript的顺序与Java相同,但异步调用更频繁。如果您希望在长时间之后调用回调,则必须在长时间运行的程序之后调用它。像这样 -

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

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

The第二次调用回调,应该在Test函数里面去掉。 – wonderbell

+0

@aSharma确实 - 我甚至没有注意到它是诚实的。 –

+0

非常感谢,但我知道这样做的特殊方式。我想也许还有其他的一些方法。我仍然不明白回调的意义,虽然:( – Savvy

0

我已经修改了您的代码,如下所示,以获得所需的输出。

console.log("Beginning"); 
function Test(callback){ 

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

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

的setTimeout需要将在指定的时间间隔

使用的setTimeout的是异步部分之后执行的回调函数。当执行上述代码时,首先打印“开始”控制台语句,然后调用Test函数传入一个函数,该函数需要在500ms后异步执行。

相关问题