我很难理解this online javascript book (You-Dont-Know-JS)中的以下功能如何工作?当传递给可能执行或可能不执行异步的第三方函数(在下一个代码段中描述)时,此函数如何启用异步行为?
function asyncify(fn) {
var orig_fn = fn,
intv = setTimeout( function(){
intv = null;
if (fn) fn();
}, 0 )
;
fn = null;
return function() {
// firing too quickly, before `intv` timer has fired to
// indicate async turn has passed?
if (intv) {
fn = orig_fn.bind.apply(
orig_fn,
// add the wrapper's `this` to the `bind(..)`
// call parameters, as well as currying any
// passed in parameters
[this].concat( [].slice.call( arguments ) )
);
}
// already async
else {
// invoke original function
orig_fn.apply( this, arguments );
}
};
}
我提供的链接还列出了以下有关如何执行asyncify(..)
的代码示例:
function result(data) {
console.log( a );
}
var a = 0;
ajax( "..pre-cached-url..", asyncify( result ) );
a++;
此处ajax(..)
是可以执行异步或同步的第三方功能。为了强制执行result(..)
的异步回调,作者以asyncify(..)
为例。这将导致控制台输出始终为1
(异步)。
据我了解,函数fist定义了两个变量orig_fn
来存储原始函数句柄result()
。 intv
是setTimeout
返回的计时器ID。
var orig_fn = fn,
intv = setTimeout( function(){
intv = null;
if (fn) fn();
}, 0 )
;
setTimeout(..,0)
的确切含义是什么?要在事件循环的下一次运行中立即执行?
为什么我们要在fn()
的回调函数中执行setTimeout
,并在return函数中执行else语句? ajax
异步操作时,函数不是以这种方式调用过两次吗?首先是计时器触发时,它调用fn()
,然后是调用orig_fn.apply(this, arguments)
时再次调用?
为什么asyncify返回一个函数,但还要调用传递给它的函数fn
?
if语句中的以下内容是什么意思,如果fn
是同步的,ajax
甚至会被调用?
fn = orig_fn.bind.apply(
orig_fn,
// add the wrapper's `this` to the `bind(..)`
// call parameters, as well as currying any
// passed in parameters
[this].concat( [].slice.call( arguments ) )
);
fn
设置为原始功能?对我来说,返回后甚至不使用变量fn
?还是对result()
的引用,现在通过添加包装器的this
和参数来更改?如果是这样,为什么需要this
的包装器? 我想了解此功能的主要问题是取决于ajax(..)
(异步或同步)的工作方式,此代码流如何工作。有人可以用这两个步骤之间发生的步骤来解释这两种情况吗?