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.