stringByEvaluatingJavaScriptFromString 如何重入?
How can stringByEvaluatingJavaScriptFromString be re-entrant?
我正在 iOS 上构建混合 native/HTML5 应用程序。作为 native/HTML5 桥的一部分,我正在通过 stringByEvaluatingJavaScriptFromString.
执行一些 JavaScript 代码
我确保从本机端的主调度队列调用此函数。大多数时候,JavaScript 端的效果是调用的 JavaScript 代码直接从顶层(JavaScript 堆栈)调用,即使多次调用 stringByEvaluatingJavaScriptFromString 发生在附近。
然而,我偶尔会看到在方法执行过程中调用 stringByEvaluatingJavaScriptFromString 的证据 - 也就是说,例如调用的方法在 stringByEvaluatingJavaScriptFromString 调用的方法开始执行之前,事件处理程序不会 return。
鉴于 JavaScript 是单线程的,这怎么可能?
这个问题困扰了我几个月,终于有了答案。
虽然 iOS 通常在 JavaScript 堆栈的顶部执行 stringByEvaluatingJavaScriptFromString 调用,但某些系统调用似乎 "yield" 未决评估。我特别指出的一个是 XmlHttpRequest.send():如果在调用 send() 时碰巧有未决的评估,send() 将阻塞直到这些评估被执行。可能还有其他人。
如果这种行为是不可取的,您可以通过将 stringByEvaluatingJavaScriptFromString 调用的函数包装在 setTimeout(..., 0) 中来避免代码重入。有关此类调用为何有用的背景信息,请参阅 this question。
编辑:虽然在写完这篇文章后我想到 xhr.send() 会执行任何未决的评估,但不会执行未决的超时,这有点奇怪。我将不得不做更多的实验...
编辑 2:实验表明 xhr.send() 实际上不执行挂起的超时。不一致有点奇怪,但就是这样。
我正在 iOS 上构建混合 native/HTML5 应用程序。作为 native/HTML5 桥的一部分,我正在通过 stringByEvaluatingJavaScriptFromString.
执行一些 JavaScript 代码我确保从本机端的主调度队列调用此函数。大多数时候,JavaScript 端的效果是调用的 JavaScript 代码直接从顶层(JavaScript 堆栈)调用,即使多次调用 stringByEvaluatingJavaScriptFromString 发生在附近。
然而,我偶尔会看到在方法执行过程中调用 stringByEvaluatingJavaScriptFromString 的证据 - 也就是说,例如调用的方法在 stringByEvaluatingJavaScriptFromString 调用的方法开始执行之前,事件处理程序不会 return。
鉴于 JavaScript 是单线程的,这怎么可能?
这个问题困扰了我几个月,终于有了答案。
虽然 iOS 通常在 JavaScript 堆栈的顶部执行 stringByEvaluatingJavaScriptFromString 调用,但某些系统调用似乎 "yield" 未决评估。我特别指出的一个是 XmlHttpRequest.send():如果在调用 send() 时碰巧有未决的评估,send() 将阻塞直到这些评估被执行。可能还有其他人。
如果这种行为是不可取的,您可以通过将 stringByEvaluatingJavaScriptFromString 调用的函数包装在 setTimeout(..., 0) 中来避免代码重入。有关此类调用为何有用的背景信息,请参阅 this question。
编辑:虽然在写完这篇文章后我想到 xhr.send() 会执行任何未决的评估,但不会执行未决的超时,这有点奇怪。我将不得不做更多的实验...
编辑 2:实验表明 xhr.send() 实际上不执行挂起的超时。不一致有点奇怪,但就是这样。