我了解回调的概念,在回调中,我将一个函数传递给另一个函数,然后该函数随便使用提供的函数。
即使在谷歌搜索之后,我仍在努力理解延迟的回调。
有人可以提供简单的解释吗?我使用Ruby编程,但也了解C / C ++,但最重要的是,我是一位经验丰富的汇编语言程序员。所以我想知道这是否有点像一堆被弹出的回调地址?我希望学习jquery或node.js,而这些延迟的回调似乎对两者都是必不可少的。我了解基本的线程处理原理(尽管互斥对象使我的头部受伤;)
我了解回调的概念,在回调中,我将一个函数传递给另一个函数,然后该函数随便使用提供的函数。
即使在谷歌搜索之后,我仍在努力理解延迟的回调。
有人可以提供简单的解释吗?我使用Ruby编程,但也了解C / C ++,但最重要的是,我是一位经验丰富的汇编语言程序员。所以我想知道这是否有点像一堆被弹出的回调地址?我希望学习jquery或node.js,而这些延迟的回调似乎对两者都是必不可少的。我了解基本的线程处理原理(尽管互斥对象使我的头部受伤;)
Answers:
根据要求,以下是作为答复提出的意见:
我不确定您是否完全理解JS中的函数是一流的对象,因此可以在创建它们之前将它们存储到需要为止。
例如,假设您要写入文件,然后打印出一条日志消息;因此,您可以调用“ write()”函数(或其他函数)并将其传递给输出日志消息的函数(这是延迟的回调函数)。“ write()”在内部存储对给定函数的引用,开始写入文件,并设置其自己的回调以知道写入何时完成。然后在完成写入之前返回。如果是,则以某种方式调用内部回调(这是基础框架的工作-在node.js的情况下,它是通过事件循环完成的),然后调用您的回调以打印日志消息。
“延迟”部分只是意味着您的回调函数不会立即被调用;调用它被推迟到适当的时间。对于像node.js中的许多异步函数那样,通常在操作完成(或发生错误)时调用给定的回调。
大多数东西在node.js中是异步的,但是在带有jQuery的浏览器中,大多数东西实际上是同步的(显然,对于AJAX请求除外)。由于一流的函数在JavaScript中非常方便(尤其是由于强大的闭包支持),因此回调也可在浏览器中的任何地方使用,但对于同步操作,它们并不“延迟”(除非它们不被立即调用)您,但稍后通过您调用的函数)。
基础系统是事件驱动的,这一事实与延迟回调的使用正交。您可以想象一个(非常慢的)版本的node.js,它为每个操作启动一个线程,然后在线程完成其工作时调用给定的回调,而完全不使用事件。当然,这是一个可怕的模型,但这说明了我的观点:-)
延迟回调的工作方式是每次向其添加回调时,该回调将被推送到数组。然后,在延迟对象上调用.resolve()
or .resolveWith()
方法时,.done()
将按顺序执行数组中的所有回调。
现在我们来看看什么是延迟对象。以下面的代码段为例。
var deferred = $.Deferred();
var promise = deferred.promise();
现在,我们有了一个延迟对象,以及该延迟对象的promise对象。递延对象具有所有相同的方法承诺对象,然而,许对象仅具有方法.done()
,.fail()
以及.always()
其用于回调添加到针对每个相应的延迟对象event
。另一方面,延迟对象还有其他几种方法,最重要的是.resolve()
和.reject()
。在延迟对象上调用这些方法时,将调用所有回调。.resolve()
将触发.done()
和.always()
回调,而.reject()
方法调用.fail()
和.always()
回调。
通常,延迟的对象保持隐藏在私有作用域内,并且Promise对象从函数返回,以便可以在其上放置回调。延迟的对象将在以后解析,例如在ajax请求完成之后或在加载图像之后,在setTimeout之后等等。认识到延迟的对象只能解析一次也很重要。如果已经解决,则将立即调用其回调。
这是我使用的另一个示例:
function loadImage(url) {
var def = $.Deferred(),
img = new Image();
$(img).on("load error",function(e){
if (e.type === "error") {
def.reject(url);
}
else {
def.resolve(url);
}
});
img.src = url;
// return the promise object so that callbacks can
// be defined on the deferred object.
return def.promise();
}
loadImage("foobar.jpg").done(function(){
alert("The image is loaded!");
}).fail(function(){
alert("The image failed to load!");
}).always(function(){
alert("This is always called!");
});
有关jQuery $.Deferred()
方法和延迟对象的更多信息,请访问http://api.jquery.com/category/deferred-object/
我不确定,但是我相信延迟回调是指异步回调,因此您会因此而获得更多的Google搜索。
我发现的最佳解释是在http://www.nodebeginner.org
嘿,大概是ExpensiveFunction(),请做您的工作,但是我,单个Node.js线程,不会在这里等到您完成为止,我将继续执行您下面的代码行,因此请您继续这个callbackFunction()在这里,当您完成昂贵的工作时调用它?谢谢!”
在此示例中,ExpensiveFunction可能是非阻塞的(或异步函数)。这意味着它不会立即执行,而是放置在所谓的事件循环中。node.js线程将继续执行,但是在某个时间点,它将决定从事件循环中执行某些操作。当到达expensiveExpensiveFunction时,将对其进行调用,并且当expensiveExpensiveFunction完成执行时,它将调用作为参数传递给它的(延迟)回调。
例如,可能使用ExpensiveFunction,可以使用fs.readFile
.resolve()
或.reject()
时,将调用回调列表。
JavaScript是单线程的,因此您无法从线程的角度来理解这一点。这是使用jQuery的常规和异步回调的示例:
var regularCallback = function(evt) {
alert("I'm a callback!")
}
var asyncCallback = function(data) {
alert("I only run when an async operation finishes!")
}
// Bind the regular callback to a button's click event
$('#mybutton').on('click', regularCallback);
// Start an ajax request to the server. The request is asynchronous, so code
// below this line will execute immediately. The callback function
// will only be called when the request is complete.
$.get("http://google.com", asyncCallback);
延迟回调(又名Promices)使您可以编写顺序异步代码,而不会感到痛苦和回调意大利面条:
$.when( doAjax(), doAnotherAjax() ).then( haveFunWithMoreAjax ).then( animateStuff );
“何时”可让您等待函数并行返回,并且then
可以顺序链接。
一个注意事项:jQuery延迟!= Promices / A,它们的语法有些不同。
关于这个话题有很多好文章:一个在IEBlog上,另一个在一些随机博客中,一本书和一个流行的stackoverflow问题
Deferred
对象吗?这是有关Node.js的特定内容吗?