支持 AMD 的库中的异步请求
Async request in library which support AMD
由于使用 XMLHttpRequest 发出的异步请求,我想要构建的库出现问题。我会用一些代码来解释:
(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;
});
我使用回调来确保我收到数据并在数据加载时定义我的模块,但是当我使用 requireJS 加载 "library" 时它仍然会在我的模块真正定义之前触发。
(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);
}
});
我用来用 requireJS 测试我的模块的另一个脚本:
require(['tof'], function(tof){
// return undefined because of my async request
console.log(tof);
});
我该如何解决这个问题?
我相信您很快就发现您的第一次尝试是行不通的,因为您不能使用同步 return
到 return 异步获得的值。
你的第二次尝试也不行。看起来您希望传递给 define
的工厂函数 异步定义模块 但 RequireJS 不允许这样做。您需要做的是以提供允许模块用户异步检索 XMLHTTPRequest
结果的功能的方式设计模块。
这是一些可能性的草图。我强调这是一个草图。我打了这个即兴的。至少,您需要添加错误处理代码:
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,
};
});
然后您可以在其他地方使用它,例如:
require(['tof'], function (tof) {
tof.getResult().then((result) => console.log(result));
});
由于使用 XMLHttpRequest 发出的异步请求,我想要构建的库出现问题。我会用一些代码来解释:
(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;
});
我使用回调来确保我收到数据并在数据加载时定义我的模块,但是当我使用 requireJS 加载 "library" 时它仍然会在我的模块真正定义之前触发。
(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);
}
});
我用来用 requireJS 测试我的模块的另一个脚本:
require(['tof'], function(tof){
// return undefined because of my async request
console.log(tof);
});
我该如何解决这个问题?
我相信您很快就发现您的第一次尝试是行不通的,因为您不能使用同步 return
到 return 异步获得的值。
你的第二次尝试也不行。看起来您希望传递给 define
的工厂函数 异步定义模块 但 RequireJS 不允许这样做。您需要做的是以提供允许模块用户异步检索 XMLHTTPRequest
结果的功能的方式设计模块。
这是一些可能性的草图。我强调这是一个草图。我打了这个即兴的。至少,您需要添加错误处理代码:
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,
};
});
然后您可以在其他地方使用它,例如:
require(['tof'], function (tof) {
tof.getResult().then((result) => console.log(result));
});