Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Kyle Simpson asyncify函数来自您的Don';我不知道JS:Async&;演出_Javascript - Fatal编程技术网

Javascript Kyle Simpson asyncify函数来自您的Don';我不知道JS:Async&;演出

Javascript Kyle Simpson asyncify函数来自您的Don';我不知道JS:Async&;演出,javascript,Javascript,如果有人能详细解释这个函数的作用是什么? 这部分在做什么:fn=orig\u fn.bind.apply(orig\u fn 谢谢 function asyncify(fn) { var orig_fn = fn, intv = setTimeout( function(){ intv = null; if (fn) fn(); }, 0 ) ;

如果有人能详细解释这个函数的作用是什么? 这部分在做什么:fn=orig\u fn.bind.apply(orig\u fn

谢谢

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 asyncify(cb) {
    return function() {
        setTimeout(function() {
            cb.apply(this, arguments);
        }, 0);
    }
}
但我要强调的是“似乎”。也许我在上面的前后关系中遗漏了一些重要的细微差别

至于
bind.apply
,解释起来有点棘手。这两种方法都是每个函数上的方法,允许您使用指定的上下文(
this
)调用它,在
apply
的情况下,它接受作为数组的参数

当我们“应用”
bind
时,bind本身就是正在应用的函数——而不是apply所在的对象,它可能是任何东西。因此,如果我们像这样重写它,可能更容易理解这一行:

Function.prototype.bind.apply(...)
Bind具有如下签名:
.Bind(上下文,arg1,arg2…)

参数是可选的——通常用于curry,这是
bind
的主要用例之一。在这种情况下,作者希望将原始函数绑定到(1)当前
this
上下文,(2)“异步化”的参数函数是用调用的。因为我们事先不知道需要传递多少个参数,所以必须使用apply,其中的参数可以是数组或实际的
参数
对象。下面是对本节的详细重写,可能有助于说明发生了什么:

var contextOfApply = orig_fn;
var contextWithWhichToCallOriginalFn = this;

var argumentArray = Array.prototype.slice.call(arguments);

argumentArray.unshift(contextWithWhichToCallOriginalFn);

// Now argument array looks like [ this, arg1, arg2... ]
// The 'this' is the context argument for bind, and therefore the
// context with which the function will end up being called.

fn = Function.prototype.bind.apply(contextOfApply, argumentArray);

实际上…

我可以解释我提供的简单版本的不同之处。在再次回顾它时,我发现它缺少的细微差别是什么,导致它的作者在顶部经历了奇怪的舞蹈。它实际上不是一个使另一个函数“始终异步”的函数。这是一个只确保异步一次的函数—它防止在创建回调的同一时间执行回调,但此后,它会同步执行

不过,我认为,还是可以用更友好的方式来写这篇文章:

function asyncify(cb) {
    var inInitialTick = true;

    setTimeout(function() { inInitialTick = false; }, 0);

    return function() {
        var self = this;
        var args = arguments;

        if (inInitialTick)
            setTimeout(function() { cb.apply(self, args); }, 0);
        else
            cb.apply(self, args);
    }
}
现在我应该注意到,上面所说的实际上并没有实现。事实上,使用超时与同步执行函数的次数在使用此版本或原始版本时是随机的。这是因为setTimeout是一个跛脚(但有时很好)代替setImmediate,这显然是这个函数真正想要的(但如果它需要在Moz&Chrome中运行的话,可能无法实现)

这是因为传递给setTimeout的毫秒值是一种“软目标”。它实际上不会是零;事实上,如果我没记错的话,它至少会是4ms,这意味着可以传递任意数量的滴答声

想象一下,你身处一个神奇的仙境,在那里ES6的东西可以正常工作,并且对于是否要实现像setImmediate这样的基础实用程序没有任何奇怪的纠结,它可以这样重写,然后它就会有可预测的行为,因为与0的setTimeout不同,setImmediate确实确保了执行在下一次勾选时发生,而不是在以后某个勾选时发生:

const asyncify = cb => {
    var inInitialTick = true;

    setImmediate(() => inInitialTick = false);

    return function() {
        if (inInitialTick)
            setImmediate(() => cb.apply(this, arguments));
        else
            cb.apply(this, arguments);
    }
};

实际上…


还有一个区别。在原始版本中,如果在“当前勾号实际上是任意数量的连续勾号”期间调用它仍然只会执行一次初始时间,并带有最后一组参数。这实际上闻起来有点像是意外行为,但没有上下文,我只是猜测;这可能正是预期的结果。这是因为在第一次超时完成之前的每次调用中,fn都会被覆盖。这种行为有时被称为thrott但在这种情况下,与“正常”节流不同的是,它只会在创建后4ms左右的未知时间内发生,此后将被解除锁定并同步。祝调试这样调用的Zalgo的人好运:)

检查intv是因为如果在调用asyncify()的同一个tick中调用了生成的下一个tick'd函数,则仍然会定义intv。但我说不出orig_fn vs fn的意义是什么。当fn绑定到orig_fn时,fn将不再使用,除非在该赋值中使用——换句话说,赋值是无意义的(除非我只是缺少了一些东西……)@Semicolon:
fn
setTimeout
回调中被调用,这可能在调用它返回的设置
fn
的函数之后发生,也可能不会发生,我刚在键入后看到它,并准备对编辑进行注释:)(也就是说,我发现这里所做的部分很难理解。也就是说,如果没有看到如何使用它的示例,很难理解,例如,为什么它最初执行回调,但又返回一个函数以再次执行).我还应该向OP指出,
orig_fn.bind.apply
非常奇怪。它实际上与
Function.prototype.bind.apply相同,因此对orig_fn的引用可能会混淆;为了方便起见,我们将其从中提取出来,然后在调用apply时提供orig_fn作为上下文)。感谢您对分号的解释。关于异步调用,您是对的,它必须是第一次异步,然后才是同步。这一个仍然在旋转我的世界:fn=orig_fn.bind.apply(orig_fn,[this].concat([].slice.call(arguments))。我不明白他想在这里做什么…我已经对这一部分做了更深入的描述。orig_fn.bind.apply(orig_fn,…与Function.prototype.bind.apply相等吗(orig_fn,…再次感谢您花时间回答我。Function.prototype是object。它是原型的一种方法,所有函数都从原型继承。我强调了这一点,因为在那一行中,第一个
orig_fn
实际上并没有“使用”,只是为了抓住这个通用方法。(换句话说,使用
orig_fn
可以任意简写“任何函数,我只想做点什么