Question about the code : Why is it that sometimes window.setTimeout is used instead of the global setTimeout ?
It is kind of an issue because I cannot use BabylonJs in a test environnement where window.setTimeout is not defined (not in the browser).
Yes, I can redefine window.setTimeout on my side but it might be better to always use the global setTimetout. Do that sound a good idea ? Can I make a PR for that ?
Thanks in advance for you anwser and Happy New Year to all of you
Julien
My tests run in node with jest within a create-react-app, NOT in the browser.
If I don’t add some code like global.window.setTimeout = setTimeout I have this error when running the test :
TypeError: window.setTimeout is not a function
at Function.ThinEngine.QueueNewFrame (../lts/core/generated/Engines/thinEngine.ts:5896:27)
at NullEngine.ThinEngine._queueNewFrame (../lts/core/generated/Engines/thinEngine.ts:1612:27)
at NullEngine.runRenderLoop (../lts/core/generated/Engines/thinEngine.ts:1629:39)
I’m sorry but that is true, in the browser, calling window.setTimeout is equivalent to setTimeout. And that’s excactly what you mean when you say
that the global object is the window object
And in IMHO there is no point calling window.setTimeout, especially if both are used in the very same function :
public static QueueNewFrame(func: () => void, requester?: any): number {
if (!IsWindowObjectExist()) {
if (typeof requestAnimationFrame !== "undefined") {
return requestAnimationFrame(func);
}
return setTimeout(func, 16) as unknown as number;
}
if (!requester) {
requester = window;
}
if (requester.requestPostAnimationFrame) {
return requester.requestPostAnimationFrame(func);
} else if (requester.requestAnimationFrame) {
return requester.requestAnimationFrame(func);
} else {
return
window.setTimeout(func, 16)
}
}
Whether setTimeout returns different type of value between in the Browser/NodeJs is another question, and actually the return type is not really problem as its only purpose is to identify the timer to be able to clear it with clearTimeout
Actually I just read more carefully the piece of I pasted above, the problem might come from that function. Testing if the window object is defined is not enough, we should also test if window.setTimeout exists
This absolutely depends on what environment is your app running in, but you can’t generalize this. Ofcourse if you open the console and try it there it’s true but you can’t rely on it in any other environment.
you wouldn’t need to cast to unknown because windows.setTimeout always returns a number so you are doing it to satisfy the TS compiler because it doesn’t know which version of setTimeout are you referring to.
Ok, you might have got me wrong, so I rephrase it:
in the browser, calling window.setTimeout is the very same thing as callling setTimeout, because window is the global object. So in this case, there is not difference. We could just call setTimeout.
If not in the browser, then window might not be the global object, that’s right, but also it might not has a setTimeout method. So we should make sure that window.setTimeout is defined before calling it and fallback to the global setTimeout if it is not defined.
Buuut you can run a webpack/vite/parcel etc app in the browser where setTimeout could resolve not to the global window.setTineout function. You know what I mean…
By the way, having setTimeout and window.setTimeout to be different functions looks a bit dangerous to me, if not weird. And I’m not sure which one the user is expecting BabylonJs to call…
ok sorry , i didnt understand what was meant by “not in a browser” although I cant say im too happy to hear such things, fragmentation in how you have to write javascript now for different platforms or frameworks is not ideal.
TypeScript helps as a lot when it comes to typing in different environments. If you use ReturnType<setTimeout> as the type of the object you get from a setTimeout call your framework (for example Babylon ;-)) can run in both node.js and the browser, even if they have a different return type for this specific function.
Having said that, I am officially criticizing Node.js for choosing to go this path, as it makes little sense to me to change a web standard just because you think you know better. I mean, they might know better, but that would only lead to problems in different environments. As we see here… But that’s a whole different story