如何知道Javascript回调是同步还是异步?

时间:2017-12-08 18:12:50

标签: javascript

嗨!我正在学习回调,我知道回调可以是同步的也可以是异步的。

我正在阅读关于https://www.w3schools.com/jquery/jquery_callback.asp的回调,并且非常困惑。

有这个代码:

$("button").click(function(){
    $("p").hide("slow", function(){
        alert("The paragraph is now hidden");
    });
}); 

我可以检查是否有办法知道上述回调是同步还是异步?

我猜它是同步的,因为它必须等到警报出现之前“慢”动画结束。默认情况下,在Javascript或Node.js中,除非您执行setTimeOut或process.nextTick之类的操作,否则所有回调都是同步的吗?

5 个答案:

答案 0 :(得分:3)

这里有几个问题,所以我会尝试逐一回答:

  

默认情况下,在Javascript或Node.js中,除非您执行setTimeOut或process.nextTick等操作,否则所有回调都是同步的吗?

在浏览器中,您可以将此作为经验法则:只有setTimeoutsetInterval,请求和事件是异步的。其他内置回调(如Array.prototype.map)是同步的。

在Node.js上它更复杂:例如您可以同时阅读synchronouslyasynchronously的文件。然后你只需要知道回调本质上是异步的。

  

我可以检查是否有办法知道上述回调是同步还是异步?

不幸的是,如果没有检查您调用的方法/功能的源代码,您无法知道它是同步还是异步。

  

我猜它是同步的,因为它必须等到"慢"在警报出现之前动画结束。

完全。您可以从jQuery's documentation for .hide method找到:

  

<强>完整
  类型:功能()
  动画完成后调用的函数,每个匹配元素调用一次。

答案 1 :(得分:1)

回调是一个异步过程完成后将执行的函数。假设我们有一个包含以下数据的对象person

var person = {
 id: 1034
 name: Julio,
 age: 23,
 moneyInBank: 0
}

我们希望获得此人的moneyInBank,但我们无法在本地环境中访问该信息。我们需要从另一台服务器的数据库中获取它,这可能需要一段时间,具体取决于互联网连接,优化等。

getMoneyInBank(person.id, callback)将继续执行该过程并获取我们需要的信息。如果我们在没有回调的情况下运行下一个脚本。

getMoneyInBank(person.id);
console.log(person.money);

我们将在输出中得到0,因为getMoneyInBank在执行日志时尚未完成。如果我们想确保打印有意义的信息,我们需要将代码更改为类似的内容。

getMoneyInBank(persion.id, function(){
  console.log(person.money);
});

使用回调只会在getMoneyInBank完成时调用日志。

答案 2 :(得分:1)

您可以轻松查看:

<?php
$address = '77-379 North End road, London London SW61NP, United Kingdom'; // Your address(Please USe exist address)
$prepAddr = str_replace(' ','+',$address);

$geocode=file_get_contents('https://maps.google.com/maps/api/geocode/json?address='.$prepAddr.'&key=API_KEY&sensor=false');
$output= json_decode($geocode);


if ( isset($output->results) ) {
    if ( isset($output->results[0]) ) {
        if ( isset($output->results[0]->address_components) ) {
            foreach ($output->results[0]->address_components as $key => $value) {   
                if ( isset($value->types) ) {
                    if ( isset($value->types[0]) ) {
                        if($value->types[0] == 'country'){
                            print_r($value->short_name); //GB
                        }
                    }
                }
            }
        }
    }
} ?>

答案 3 :(得分:1)

简答: 您需要检查调用者并查找异步操作。

答案很长:

回调是一种简单的模式,通过该模式,函数作为参数传递给更高阶的函数,并在堆栈中向下或向下调用。

let mySynchronousFunction = () => 'Hello';
let myHigherOrderFunction = aFunc => {
    return (aFunc() || 'Goodbye') + ' world!';
};

只要存在阻止主线程的I / O操作,它就会“分支”并继续执行。

如果我们继续上一个示例,我们会发现以下行为:

let myAsyncFunction = () => {
    return http.get('http://some.document')
       .then(response => console.log(response)
    );
};
myHigherOrderFunction(mySynchronousFunction); // 'Hello world!'
myHigherOrderFunction(myAsyncFunction); // 'Goodbye world!'

这里发生的事情是主线程一直持续到它必须等待I / O而不是在那里阻塞,它转到下一条指令并注意到它需要去的时刻I / O操作不再被阻止。

因此,我们代码中的下一个评估表达式是:

return expression

但是我们的表达式扩展了,因此返回undefined。所以我们留下:

return undefined

这意味着我们通过异步函数的高阶函数在调用aFunc()时得到 undefined

完成I / O后,主线程返回到它停止的位置,即传递给Promise处理程序然后的函数。此时,执行线程已扩展并与主“线程”分开。

现在提出您的问题

当调用它的高阶函数同步调用它时,回调将是同步的。反过来,如果在异步操作的执行分支的上下文中调用它,它将是异步的。

这意味着您需要检查传递回调的高阶函数正在执行的操作并查找异步操作。

在您的问题的上下文中,让我们检查以下代码(HOF =高阶函数):

let mySynchronousHOC = aFunc => aFunc('Hello world!');
let myAsyncHOC = aFunc => {
    http.get('http://hello.com')
        .then(response => aFunc('Goodbye world!')
    );
};

myAsyncHOC(msg => {
    console.log(msg);
});

mySynchronousHOC(msg => {
   console.log(msg);
});

结果将是:

'Hello world'
'Goodbye world'

我们知道myAsyncHOC是异步的,因为它执行I / O操作。

答案 4 :(得分:0)

我不确定“同步”和“异步”在这种情况下是否有意义。在发出ajax请求时,你可以谈论同步或异步,这意味着在同步请求中,其他一切都会在收到响应之前停止,而在异步请求中,在服务器发送响应之前可能会发生其他事情。

在您的特定情况下(https://www.w3schools.com/jquery/jquery_callback.asp)会发生什么:

  • 在“慢”情况下设置超时并在时间结束时调用回调

  • 在第二种情况下,为隐藏段落设置了超时,但在时间结束之前,在下一行上立即调用该函数

这不是同步/异步,而是关于事件编程