嗨!我正在学习回调,我知道回调可以是同步的或异步的。
我在https://www.w3schools.com/jquery/jquery_callback.asp上阅读回调,并且很困惑。
有这样的代码:
$("on").click(function(){
$("p").hide("slow", function(){
alert("The paragraph is now hidden");
});
});
我可以检查是否有办法知道上面的回调是同步还是异步?
我猜它是上面的 Synchronous,因为它必须等到“慢”动画结束后才会出现警报。默认情况下,在 Javascript 或 Node.js 中,所有回调都是同步的,除非你做类似 setTimeOut 或 process.nextTick?
您这里有几个问题,所以我将尝试一一回答:
默认情况下,在 Javascript 或 Node.js 中,所有回调都是同步的,除非您执行 setTimeOut 或 process.nextTick 之类的操作?
在浏览器中,您可以将此作为经验法则:只有setTimeout
,setInterval
,请求和事件是异步的。其他内置回调(如Array.prototype.map
)是同步的。
在 Node.js 上,它更复杂:例如,您可以执行文件读取synchronously和asynchronously。然后,您只需要知道回调本质上是异步的。
我可以检查是否有办法知道上面的回调是同步还是异步?
Unfotunately 没有检查您正在调用的方法 / 函数的源代码,您无法知道它是同步还是异步。
我猜它是同步的,因为它必须等到“慢”动画结束之前,警报出现。
没错。你可以从jQuery's documentation for .hide
method找到这个:
complete
类型:Function()
动画完成后调用的函数,每个匹配的元素调用一次。
回调是一个函数,一旦异步进程完成,它就会被执行。假设我们有一个包含以下数据的对象person
。
var person = {
id: 1034
name: 'Julio',
age: 23,
moneyInBank: 0
}
我们想获得这个人的moneyInBank
,但我们在本地环境中无法访问该信息。我们需要从另一台服务器的数据库中获取它,这可能需要一段时间,具体取决于 Internet 连接,优化等。
getMoneyInBank(person.id, callback)
将遍历该过程并获取所需的信息。如果我们要在没有回调的情况下运行下一个脚本。
getMoneyInBank(person.id);
console.log(person.money);
我们将在输出中得到 0,因为getMoneyInBank
在执行日志时尚未完成。如果我们想确保我们将打印有意义的信息,我们需要将代码更改为这样。
getMoneyInBank(persion.id, function(){
console.log(person.money);
});
使用回调,只有当getMoneyInBank
完成时才会调用日志。
您可以轻松检查:
function isSync(func, ...args){
var isSync = false;
const res = func(...args, r => isSync = true);
if(res instanceof Promise) res.then(r => isSync = true);
return isSync;
}
console.log( isSync([].map.bind([])) );
简短答案:您需要检查调用方并查找异步操作。
长答案:
回调是一种简单的模式,通过它将函数作为参数传递给更高阶的函数,并将其回调或进一步向下调用。
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 操作。
本站系公益性非盈利分享网址,本文来自用户投稿,不代表码文网立场,如若转载,请注明出处
评论列表(80条)