在Javascript中查询本地值的首选方法是什么?
例如,有一个名为animationComplete
的variables(来自第三方库)和一个名为happenAfterAnimation
的函数:
一个简单的解决scheme如下所示:
while(!animationComplete) { // Do nothing } happenAfterAnimation()
或者像这样一个更复杂的解决scheme:
function tryHappenAfterAnimation() { if(animationComplete) { happenAfterAnimation() } else { setTimeout(tryHappenAfterAnimation, 100) } } setTimeout(tryHappenAfterAnimation, 100)
第一个解决scheme可能有一些开销,第二个解决scheme看起来有点脏。
由于future/promise
是不是在当前版本的Javascript中可用,它的方式可能有点矫枉过正这里..我只是想知道是否有一个优雅和轻量级的方式来处理这种情况..
有没有人有更好的方式来处理这个想法? 谢谢!
第一种方法根本行不通。 它会永远阻塞线程。
没有内置的承诺支持并不是真正的借口不使用承诺。 如果你的图书馆给你一个事件/callback驱动的方式来等待结果(如果没有,我会感到惊讶),那么你应该使用一个事件或承诺。
如果没有,并且查询variables真的是你唯一的select,那么我会说你的第二种方法几乎是唯一的select。
快速总结 – 你的第一个方法将无法工作(这将只是一个无限循环)和轮询机制(虽然它可以使工作)从来没有“首选”的select。
Javascript是单线程的(有一些例外,比如webWorkers,但是它们在这里不适用),只要你的while循环运行,没有其他JS可以运行,可能会改变animationComplete
的值,所以你会有一个无限循环将永远不会完成(最终浏览器会抱怨JS线程还没有完成,并提供给用户停止脚本的机会)。
知道animation完成的正确方法是使用callback来完成animation。 如果你使用的是jQuery,那么所有的jQueryanimation都有一个完成callback,你可以传递它,当animation完成时它会被调用。 然后,您将在callback函数中的animation后发生的代码。
如果您正在使用CSS3animation,则可以为transitionend
事件注册一个事件处理程序,并在animation完成时以这种方式获取callback。
如果你想轮询一个variables的值,那么使用一个计时器轮询它将是一个合适的select,因为这允许其他代码运行,实际上可以改变variables。
我应该补充说,这样的投票很less是最好的deviseselect。 如果它是一个animation,那么你只是想在animation上使用一个完成事件,所以不需要轮询。 如果出于某种原因,您正在使用一个没有内置完成事件的animation函数,那么可能需要修改该代码来包含这样一个callback,因为它总是可能的,而且显然是有用的。
为了提供更详细的build议,我们需要更多地了解animation代码以及您正在尝试做什么。 正如我之前所说,所有的jQueryanimation提供承诺和callback支持完成通知(你没有标记问题jQuery是为什么我提到)。
在任何接口中缺乏承诺并不是不使用完成callback的原因,因此事实在这里没有真正的相关性,并且任何给定的函数也可以被普遍化(如果承诺是期望的方式,则将简单的callback变成承诺接口)与asynchronous事件交互。
这是一个基于Promise的方法。 以下实现定期轮询和超时。
var Promise = require('bluebird'); /** * Periodically poll a signal function until either it returns true or a timeout is reached. * * @param signal function that returns true when the polled operation is complete * @param interval time interval between polls in milliseconds * @param timeout period of time before giving up on polling * @returns true if the signal function returned true, false if the operation timed out */ function poll(signal, interval, timeout) { function pollRecursive() { return signal() ? Promise.resolve(true) : Promise.delay(interval).then(pollRecursive); } return pollRecursive() .cancellable() .timeout(timeout) .catch(Promise.TimeoutError, Promise.CancellationError,function () { return false; }); }
你这样称呼。
poll(animationComplete, pollingInterval, timeout) .then(function(complete) { if (complete) happenAfterAnimation(); } );
请参阅承诺的Javascript轮询 。