强制回调为异步

时间:2017-11-07 17:45:52

标签: javascript

所以我正在使用this指南来了解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 );
        }
    };
}

用法:

function result(data) {
    console.log( a );
}

var a = 0;

ajax( "..pre-cached-url..", asyncify( result ) );
a++;

所以从概念上讲,我理解它试图强制一个立即执行的函数,在事件循环的下一个刻度上运行,这允许变量a设置为值1,因此将始终打印1。 / p>

setTimeout部分是我假设的部分,它将调用推送到事件循环的下一个tick。但是,我完全迷失在代码的返回部分。

问)我知道intv将是计时器ID,究竟是orgin_fn.bind.apply的黑魔法意味着什么。我知道bind,ahem将一个值绑定到稍后要调用的函数,apply会传递一个this对象和参数数组,但是我很难理解整个调用流程,而且我从未见过fb.bind.apply。 / p>

Q)当我在浏览器中运行代码时,此对象解析为Window,为什么所有参数都在窗口(本例中为全局)对象上连接。

问)我理解这是POC,但是有一个合理的理由在这里有一个以任何方式执行函数的else块。我在哪种情况下看到这个被执行。

干杯!

1 个答案:

答案 0 :(得分:1)

orig_fn.bind.apply是替代同步回调。它正在创建一个新函数,当调用它时,将使用相同的this调用原始函数并调用它(替换),并将该函数分配给fn。这样,以后当计时器关闭并调用fn时,它会使用正确的this和参数调用原始函数。 (请参阅Function#bindFunction#apply;棘手的一点是它在apply上使用bind,为orig_fn传递this bind {1}}致电。)

if / else是这样的,如果在计时器关闭之前调用替换(intv是真的),它就不会立即调用orig_fn ,它等待上述操作并将结果分配给fn。但是如果计时器已经关闭(intvnull并且因此是假的),它会立即同步调用原始函数。

通常情况下,您不希望创建一个像这样混乱的函数(有时异步执行某些操作,有时同步执行),但在这种特殊情况下,原因是它确保它包装的函数是始终异步调用:如果在调用asyncify的同一作业/任务*期间调用该函数,它将等待调用原始函数,直到计时器触发为止;但是如果它已经在不同的工作/任务上,那么它就会立即完成。

该功能的更现代版本可能使用承诺,因为在当前环境中,承诺结算回调在当前作业之后尽快发生;在浏览器上,这意味着它发生在计时器回调之前。 (Promise解决回调是所谓的“微任务”与计时器和事件“macrotasks”。在macrotask完成时,在任何先前安排的下一个macrotask之前执行macackask期间安排的任何微任务。)

* job = JavaScript terminology,task = browser terminology