The documentation for evaluateAsync
does not say much so I'm going to take it at face value and assume that it just executes the code asynchronously, without any further constraint regarding what may or may not have loaded already. (The source code does not indicate any further constraints either.)
The problem I'm seeing is that you have two asynchronous functions that may execute in any order. When require(['main'], ...)
is called, this tells RequireJS to start loading the module but you don't know when the module will actually load. Similarly, when you execute page.evaluateAsync
you are telling PhantomJS to execute a piece of code asynchronously. So it will execute but you don't know when.
So the following can happen:
The module finishes loading: window.myglobal
is set.
console.log
is called, which outputs the correct value.
Or:
console.log
is called, which fails.
The module finishes loading: window.myglobal
is set.
Setting a timeout that delays the execution of console.log
will make it more likely that the first case happens but it does not guarantee it.
What you could do is change your HTML like this:
<body>
<script>
require.config({
base: '.',
paths: {
main: 'main'
}
})
define('init', ['main'], function () {
window.myglobal = {
something: 'foo'
};
});
require(['init']);
</script>
</body>
Your PhantomJS script:
page.evaluateAsync(function() {
require(['init'], function () {
console.log(window.myglobal.something); // Should print out 'foo'.
});
});
What this does is define a module called init
. (This is a rare case where explicitly naming your module with define
is okay. Usually you just start the define
call with the list of dependencies.) Then when evaluateAsync
is called it asks for the init
module, which guarantees that the assignment to window.myglobal
will have happened before console.log
runs.
It would also be possible to use promises to get the desired results but I've preferred to show a solution that uses only RequireJS.