I have a problem with a library I want to build because of async request I made with XMLHttpRequest. I will explain with some code :
(function(root,factory){
if( typeof define === "function" && define.amd ){
// AMD module
define([], factory);
}else{
global.tof = factory();
}
})(this, () => {
const obj = {
datas: {},
get: function(){}
...
}
const url = "...";
let request = new XMLHttpRequest();
request.open('GET',url);
request.responseType = 'json';
request.send();
request.onload= function(){
obj.datas = request.response;
}
return obj;
});
I worked with callback to be sure I receive data and define my module when data has loaded but when I load the "library" with requireJS it still fires before my module is really defined.
(function(root,factory){
function myCallback(r){
if( typeof define === "function" && define.amd ){
// AMD module
define('tof',[], factory(function(r){
return r;
}));
}
}
factory(myCallback);
})(this, function foo(callback){
const obj = {
datas: {},
get: function(){}
...
}
const url = "...";
let request = new XMLHttpRequest();
request.open('GET',url);
request.responseType = 'json';
request.send();
request.onload= function(){
obj.datas = request.response;
callback(obj);
}
});
My other script I used to test my module with requireJS :
require(['tof'], function(tof){
// return undefined because of my async request
console.log(tof);
});
How could I resolve this?
I'm sure you quickly figured out your 1st attempt cannot work, since you cannot use a synchronous return
to return a value obtained asynchronously.
Your 2nd attempt cannot work either. It looks like you'd like the factory function you pass to define
to define a module asynchronously but RequireJS does not allow that. What you need to do is design your module in a way that it provides a function that allows the user of the module to retrieve the result of the XMLHTTPRequest
asynchronously.
Here's a sketch of some possibility. I emphasize that this is a sketch. I typed this off-the-cuff. At the very least, you'll need to add error handling code:
define(function () {
const promise = new Promise((resolve, reject) => {
const request = new XMLHttpRequest();
request.open('GET',url);
request.responseType = 'json';
request.send();
request.onload = () => {
obj.datas = request.response;
resolve(obj);
};
});
return {
getResult: () => promise,
};
});
Then you'd use it elsewhere like:
require(['tof'], function (tof) {
tof.getResult().then((result) => console.log(result));
});