Is there an implementation of setTimeout() and clearTimeout() in Haxe?
It's of course possible to use the Timer class, but for a one-shot execution it's not the best way, I guess.
For a one-shot execution I think that Timer.delay() is perfect. You can use the returned instance to stop the timer later:
var timer = haxe.Timer.delay(function() trace("Hello World!"), 250);
...
timer.stop();
You could also access the native setTimeout() with the js.html.Window extern:
var handle = js.Browser.window.setTimeout(function() trace("Hello World!"), 250);
...
js.Browser.window.clearTimeout(handle);
In case you're using the kha framework:
Kha modifies haxe.Timer to call kha.Scheduler, which in the end doesn't get the timestamps via setTimeout - it gets these via requestAnimationFrame().
This seems to not work while a tab is inactive, so it's not the same function while the tab is inactive.
I'm attempting a workaround, but at the moment, it doesn't give the same result as a native setTimeout()-JS does (although I found a workaround which I'll present for inclusion).
Related
background
const timer = setInterval(
fetchAndUpdateMaterial({ materialId, commit, timer }),
delay,
);
and the param timer is marked by eslint: 'timer' was used before it was defined.
so I think it's not the right or elegant way to use setInterval.
target
no eslint error without using setTimeout recursively
(I'm not a native speaker, so thanks to read the problem)
I am trying to use titanium execution contexts to produce parallel code execution between the main application context and others. I am using CreateWindow with a url property refers to a .js file inside "lib" folder. But by logging the execution on both iOS and Android devices it seems that different contexts are executed on the app main thread, no parallelism here.
My new context trigger inside my Alloy controller:
var win2 = Ti.UI.createWindow({
title: 'New Window',
url: 'thread.js',
backgroundColor:'#fff'
});
win2.open();
Ti.API.log('after open');
My thread.js contents:
Ti.API.log("this is the new context");
Ti.App.fireEvent("go" , {});
while(true)
{
Ti.API.log('second context');
}
This while loop apparently blocks the main context (my Alloy controller) waiting it to exit.
Any suggestions of how can I execute some code (mainly heavy sqlite db access) in background so that the UI be responsive? (Web workers are not a choice for me).
You could try to achieve the wanted behaviour with a setInterval() or setTimeout() method.
setInterval()[source]:
function myFunc() {
//your code
}
//set the interval
setInterval(myFunc,2000) //this will run the function for every 2 sec.
Another suggested method would be to fire a custom event when you need the background behavior since it is processed in its own thread. This is also suggested in the official documentation.
AFAIK, titanium is single threaded, because JavaScript is single threaded. You can get parallel execution with native modules, but you'll have to code that yourself for each platform.
Another option is to use web workers, but I consider that to be a hack.
I've written a Firefox addon for the first time and it was reviewed and accepted a few month ago. This add-on calls frequently a third-party API. Meanwhile it was reviewed again and now the way it calls setInterval is criticized:
setInterval called in potentially dangerous manner. In order to prevent vulnerabilities, the setTimeout and setInterval functions should be called only with function expressions as their first argument. Variables referencing function names are acceptable but deprecated as they are not amenable to static source validation.
Here's some background about the »architecture« of my addon. It uses a global Object which is not much more than a namespace:
if ( 'undefined' == typeof myPlugin ) {
var myPlugin = {
//settings
settings : {},
intervalID : null,
//called once on window.addEventlistener( 'load' )
init : function() {
//load settings
//load remote data from cache (file)
},
//get the data from the API
getRemoteData : function() {
// XMLHttpRequest to the API
// retreve data (application/json)
// write it to a cache file
}
}
//start
window.addEventListener(
'load',
function load( event ) {
window.removeEventListener( 'load', load, false ); needed
myPlugin.init();
},
false
);
}
So this may be not the best practice, but I keep on learning. The interval itself is called inside the init() method like so:
myPlugin.intervalID = window.setInterval(
myPlugin.getRemoteData,
myPlugin.settings.updateMinInterval * 1000 //milliseconds!
);
There's another point setting the interval: an observer to the settings (preferences) clears the current interval and set it exactly the same way like mentioned above when a change to the updateMinInterval setting occures.
As I get this right, a solution using »function expressions« should look like:
myPlugin.intervalID = window.setInterval(
function() {
myPlugin.getRemoteData();
},
myPlugin.settings.updateMinInterval * 1000 //milliseconds!
);
Am I right?
What is a possible scenario of »attacking« this code, I've overlooked so far?
Should setInterval and setTimeout basically used in another way in Firefox addons then in »normal« frontend javascripts? Because the documentation of setInterval exactly shows the way using declared functions in some examples.
Am I right?
Yes, although I imagine by now you've tried it and found it works.
As for why you are asked to change the code, it's because of the part of the warning message saying "Variables referencing function names are acceptable but deprecated as they are not amenable to static source validation".
This means that unless you follow the recommended pattern for the first parameter it is impossible to automatically calculate the outcome of executing the setInterval call.
Since setInterval is susceptible to the same kind of security risks as eval() it is important to check that the call is safe, even more so in privileged code such as an add-on so this warning serves as a red flag to the add-on reviewer to ensure that they carefully evaluate the safety of this line of code.
Your initial code should be accepted and cause no security issues but the add-on reviewer will appreciate having one less red flag to consider.
Given that the ability to automatically determine the outcome of executing JavaScript is useful for performance optimisation as well as automatic security checks I would wager that a function expression is also going to execute more quickly.
Is there a way to stop in the middle of a function, and wait for a certain event before continuing?
Unfortunately I don't think it can be done. Once you begin execution of a function it will continue until the termination of the function. I believe what you might want to try is create two functions with a callback to the second function that is registered with the event you're listening for. However, it's tough to know that for sure since you haven't posted any code.
You should wrap the second half of your code in an anonymous function and attach it as an event handler:
function myFunction() {
firstHalfOfMyFunction();
eventEmitter.on('someEvent', function () {
secondHalfOfMyFunction();
});
}
You can use node-fibers which I use in my Common Node library.
WebRequest.BeginGetResponse returns IAsyncResult, which has a member AsyncWaitHandle.
Initially, I thought that I could just wait on that in the initiating code. But it turns out that the event is signaled as soon as the request is made and before and not after EndGetResponse is called. This seems unintuitive for me but whatever.
So, I've looked for some examples out there and there seems to be two ways of going about it.
One is simply to create a ManualResetEvent and pass that in as user state so that in the callback I can set it after EndGetResponse.
The other is to use ThreadPool.RegisterWaitForSingleObject. Something like:
ManualResetEvent waitHandle = new ManualResetEvent(false);
ThreadPool.RegisterWaitForSingleObject(asyncResult.AsyncWaitHandle,
new WaitOrTimerCallback((s, t) => { waitHandle.Set(); }), null, -1, true);
waitHandle.WaitOne();
That works even if ugly. And looking at the MSDN documentation for BeginGetResponse, that's how the code sample does it.
My question is, passing in a ManualResetEvent as user state, seems to be much simpler to me. What benefit does this ThreadPool.RegisterWaitforSingleObject bring?
You use that WaitHandle to wait for that Request to get a Response. When the WaitHandle gets a signal you know that a Response has arrived, and then you call EndGetResponse to actually get the Response.