事后如何调用回调?

时间:2014-07-04 18:57:58

标签: javascript

在下面的代码中,我不明白为什么要调用这两个回调函数。 callback01有意义,因为它在调用load之前在回调数组中。另一方面,callback02在调用加载之前没有放入数组,但控制台显示它被调用。

var callbacks = [];

function addCallback(func) {
  callbacks.push(func);
}

function load(img_url) {
  var img = new Image();
  img.onload = function() {
    console.log('loaded.');
    callbacks.forEach(function(func) { func(); } )
  };
  img.src = img_url;
}

addCallback(function() { console.log('callback01'); });
load('img/image01.png');
addCallback(function() { console.log('callback02'); });

3 个答案:

答案 0 :(得分:1)

两个回调都会触发,因为图像加载后回调会触发。加载图像需要几毫秒,这是代码加载和添加两个回调的充足时间。

据推测,这就是浏览器执行代码的方式:

// 1 - add first callback
addCallback(function() { console.log('callback01'); });

// 2 - tell JS to begin loading
load('img/image01.png');

// 3 - add second callback
addCallback(function() { console.log('callback02'); });

// 4 - image loads in the background
// 5 - the img.onload function fires and invokes each callback
// 5.a - callback 1 fires
// 5.b - callback 2 fires

答案 1 :(得分:0)

第二个addCallback行可能在load()完成时完成。如果您不希望此时使用callback02,请在load()函数定义的末尾添加它(如果这是一个选项)。

答案 2 :(得分:0)

在对javascript运行的浏览器的事件循环进行一些研究之后,似乎发生了这样的事情:

由于javascript是在单个线程中执行的,因此当代码执行时,控件不会返回到浏览器以处理事件,直到所有代码都被执行完毕。

将img.onload回调插入到事件队列中,执行callback02的addCallBack,将其自身添加到数组中,此时控制从javascript返回到事件循环,两个回调都可用调用onload回调。

var callbacks = [];

function addCallback(func) {
  console.log('addCallback: ' + (new Date()));
  callbacks.push(func);
}

function load(img_url) {
  var img = new Image();
  img.onload = function() {
    console.log('load:  ' + (new Date()));
    callbacks.forEach(function(func) { func(); } )
  };
  img.src = img_url;
}

function badsleep(duration) {
  var now = new Date().getTime();
  while((new Date()).getTime() < (now + duration));
}

addCallback(function() { console.log('callback01: ' + (new Date())); });
load('img/image01.png');
badsleep(2000);
addCallback(function() { console.log('callback02: ' + (new Date())); });

console.log('execution continues: ' + (new Date()));

结果:

addCallback: Sat Jul 05 2014 08:56:05
addCallback: Sat Jul 05 2014 08:56:07
execution continues: Sat Jul 05 2014 08:56:07
load:  Sat Jul 05 2014 08:56:07
callback01: Sat Jul 05 2014 08:56:07
callback02: Sat Jul 05 2014 08:56:07

所以看起来这是因为尽管似乎在加载函数之前和之后添加了回调,但这两个回调都在数组中。我希望无论如何,因为这使代码直截了当。