- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
如果有人能详细解释一下这个函数是干什么的?这部分在做什么: fn = orig_fn.bind.apply(orig_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(context, arg1, arg2...)
参数是可选的——它们通常用于柯里化(Currying),这是 bind
的主要用例之一。在这种情况下,作者希望将原始函数绑定(bind)到 (1) 当前 this
上下文,(2) 调用“asyncified”函数的参数。因为我们事先不知道需要传递多少参数,所以我们必须使用 apply,其中参数可以是数组或实际的 arguments
对象。这是对本节的非常冗长的重写,可能有助于阐明发生的情况:
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 的毫秒值是一种“软目标”。它实际上不会为零;事实上,如果我没记错的话,它总是至少 4 毫秒,这意味着任何数量的滴答声都可能通过。
想象一下,你在一个神奇的仙境,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 都会被覆盖。这种行为有时被称为节流,但在这种情况下,与“正常”节流不同,它只会在创建后 4 毫秒左右的未知时间长度内发生,此后将不受节流和同步。祝那些必须调试由此调用的 Zalgo 的人好运 :)
关于javascript - Kyle Simpson asyncify 函数来自你不知道的 JS : Async & Performance,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30383542/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!