如果我们需要等待

时间:2016-08-24 04:14:53

标签: javascript multithreading asynchronous

我已阅读Why do I have to use await for a method to run asynchronously. What if I don't want to wait for the method to finish before continuing?Are callbacks always asynchronous?,我仍在尝试了解回调实际上是异步的。

例如,doThat需要等待GET数据才能执行任何操作。并且正如上面的第二个链接所述,javascript是单线程的。

doThis(doThat);

function doThis(callback) {
    $.get('http://some_api/some_resource', function (data) {
        callback(data);
    });
};

function doThat(data) {
    // Do something with data
};

我见过的唯一真正的异步功能是承诺和多个承诺,例如,我可以在动画结束时加载其他数据。当传统的回调实际上是异步的时候,我想帮助更好地理解。具体的例子有帮助。

2 个答案:

答案 0 :(得分:4)

从定义开始:

  

异步,在计算机编程中,指的是独立于主程序流的事件的发生以及处理这些事件的方法。这些可能是"外面"事件,例如信号的到达,或程序发起的与程序执行同时发生的动作,而不会阻止程序等待结果。

- 戴维斯,亚历克斯(2012年)。 C#5.0中的异步,通过维基百科Asynchrony (computer programming)

在JavaScript的情况下,它的工作方式如下(简化):有一个任务队列等待主(也是唯一)线程执行。加载脚本时,它是放在此队列上的任务。任务一直运行直到它退出,没有其他任务可以中断它。但是,任务可以导致其他任务放在队列中。当一个任务完成时,队列上的下一个任务开始。如果队列为空,则之后进入队列的第一个任务立即执行。

任务进入队列的主要方式,除了作为被解析和执行的脚本的主要任务之外:触发事件会将为该事件注册的处理程序放在任务队列中,并达到由{{1}计划的时间或setTimeout将关联的任务放在任务队列上。

在JavaScript上下文中,在相同任务("主程序流")中执行的所有内容都被称为同步。在 future 任务中执行的所有操作都称为异步。另一种说法是 - 如果下一个语句在回调之前执行,则它是异步的;如果下一个语句在回调后执行,则它是同步的。

setInterval是一个异步调用,因为执行函数$.get(opts, callback)的任务将在callback事件触发时放在任务队列中。如果你有一个声明,它将首先被执行;只有在该任务完成后,由于对AJAX调用的更新而进入任务队列的任务才有可能运行。

相反,onreadystatechange是同步调用,因为$.each(collection, callback)将直接从callback函数调用,而不退出当前任务,并且不会生成任何其他任务(不无论如何,each当然可以产生额外的任务)。下一个语句必须等到callback完成迭代each的每个元素。

请注意,promises只是这个机制的包装器。你可以用promises做的一切,你可以没有它们,只是代码不会那么漂亮和清晰。

答案 1 :(得分:1)

  例如,我可以在动画结束时加载其他数据。

这正是您可以使用代码执行的操作。请注意,在等待doThat执行时,您可以运行其他代码(实际上“运行其他代码”会让人感到困惑)。完全像你的动画示例:

function doThis(callback) {
    $.get('http://some_api/some_resource', function (data) {
        callback(data);
    });
};

function doThat(function (data) {
    // Do something with data
});

function doAnotherThing(function (data) {
    // Do something with data
});

doThis(doThat);

// without waiting for doThat to run, you can IMMEDIATELY call:
doThis(doAnotherThing);

// without waiting for either doThat or doAnotherThing you
// can output some pretty animations:
setInterval(do_animation,100);

// and without waiting for any of the above you can do anything else:
document.body.innerHTML += 'hello';

请注意,让大多数人感到困惑的是document.body.innerHTML='hello'部分运行之前上面的任何代码。这意味着回调是异步的,因为它们在数据到达时执行 ,而不是在调用函数时执行。

请注意,并非所有回调都是异步的。例如,Array.prototype.forEach()是同步的:

document.body.innerHTML += 'before<br>';
['hello','world'].forEach(function(x){
    document.body.innerHTML += x;
})
document.body.innerHTML += '<br>after';

什么决定回调是异步还是同步的天气是调用它的函数。另见:I know that callback function runs asynchronously, but why?