Javascript 可以保证按顺序加载多个URL吗?
给出以下代码段:Javascript 可以保证按顺序加载多个URL吗?,javascript,promise,Javascript,Promise,给出以下代码段: function get(url) { return new Promise(function(resolve, reject) { var req = new XMLHttpRequest(); req.open('GET', url); req.onload = function() { if (req.status == 200) { resolve(req.response); } els
function get(url) {
return new Promise(function(resolve, reject) {
var req = new XMLHttpRequest();
req.open('GET', url);
req.onload = function() {
if (req.status == 200) {
resolve(req.response);
}
else {
reject(Error(req.statusText));
}
};
req.onerror = function() {
reject(Error("Network Error"));
};
req.send();
});
}
此功能可按如下方式使用:
get('story.json').then(function(response) {
console.log("Success!", response);
}, function(error) {
console.error("Failed!", error);
});
我想使用promise加载多个URL,例如
get('a.json').get('b.json')
// or get('a.json').then().get('b.json')
我已经用其他方式实现了它。但据我所知,允诺不能做这项工作。真的吗
添加
事实上,我实现了一个类似的库来帮助在浏览器中执行动态脚本:
Loader = (function() {
var load_cursor = 0;
var load_queue;
var loadFinished = function() {
load_cursor ++;
if (load_cursor < load_queue.length) {
loadScript();
}
}
function loadError (oError) {
console.error("The script " + oError.target.src + " is not accessible.");
}
var loadScript = function() {
var url = load_queue[load_cursor];
var script = document.createElement('script');
script.type = "text/javascript";
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" ||
script.readyState == "complete"){
script.onreadystatechange = null;
loadFinished();
}
};
} else { //Others
script.onload = function(){
loadFinished();
};
}
script.onerror = loadError;
script.src = url+'?'+'time='+Date.parse(new Date());
document.body.appendChild(script);
};
var loadMultiScript = function(url_array) {
load_cursor = 0;
load_queue = url_array;
loadScript();
}
return {
load: loadMultiScript,
};
})(); // end Loader
// load...
Loader.load(['http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js', './my.js']);
Loader=(函数(){
var load_cursor=0;
var负载队列;
var loadFinished=函数(){
加载光标++;
if(加载游标<加载队列长度){
loadScript();
}
}
函数加载错误(oError){
错误(“脚本“+oError.target.src+”不可访问。”);
}
var loadScript=函数(){
var url=load_队列[load_游标];
var script=document.createElement('script');
script.type=“text/javascript”;
if(script.readyState){//IE
script.onreadystatechange=函数(){
如果(script.readyState==“已加载”||
script.readyState==“完成”){
script.onreadystatechange=null;
loadFinished();
}
};
}其他{//其他
script.onload=函数(){
loadFinished();
};
}
script.onerror=loadError;
script.src=url+'?'+'time='+Date.parse(new Date());
document.body.appendChild(脚本);
};
var loadMultiScript=函数(url\u数组){
加载光标=0;
load_queue=url_数组;
loadScript();
}
返回{
load:loadMultiScript,
};
})(); // 端部装载机
//加载。。。
Loader.load(['http://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.0/jquery.min.js“,”./my.js']);
您可以加入承诺,在这种情况下,您必须从成功回调返回下一个承诺
get('story.json').then(function(response) {
console.log("Success!", response);
return get('b.json');
}, function(error) {
console.error("Failed!", error);
}).then(function(res){
// response for b
});
使用普通承诺语法
连锁承诺
如果你想让你的承诺循序渐进,你可以将它们连成链条:
get('a.json').then(function(a) {
return get('b.json');
}).then(function(b){
return get('c.json');
}).then(function(c) {
// all done here
}), function(err) {
// error here
});
或者在ES7中,您可以像这样使用async/await
:
async function someFunction() {
let a = await get('a.json');
let b = await get('b.json');
// do something with a and b here
return something;
}
someFunction().then(result => {
// all done here
}).catch(err => {
// error here
});
并行运行承诺
如果希望并行加载,可以使用Promise.all()
:
使用.reduce()排序
或者,如果使用相同的代码处理每个结果,则可以使用reduce()
设计模式按顺序加载它们:
['a.json', 'b.json', 'c.json'].reduce(function(p, item) {
return p.then(function(){
// process item here
});
}, Promise.resolve()).then(function(result) {
// all done here
}, function(err) {
// error here
});
使用Bluebird的.map()进行排序
或者,如果使用Bluebird promise库,它有promise.map()
,这对于阵列上的并行操作非常有用
Promise.map(['a.json', 'b.json', 'c.json'], function(item) {
// do some operation on item and return data or a promise
return something;
}).then(function(results) {
// all done
}, function(err) {
// error here
});
使
get(x).get(y).get(z)
工作
扩展承诺
我对使用承诺的get(x).get(y).get(z)
问题很感兴趣。在这个工作片段中,我想出了一个方法:
函数get(url){
函数pget(u){
var p=这个。然后(函数(结果){
日志(结果);
返回get(u);
});
p、 get=pget;
返回p;
}
var p=新承诺(功能(解决、拒绝){
setTimeout(函数(){
解析(url);
}, 500);
});
p、 get=pget;
返回p;
}
get('a.json')。get('b.json')。get('c.json')。然后(函数(结果){
日志(结果);
日志(“完成”);
},函数(err){
日志(“err”);
});
函数日志(x){
var div=document.createElement(“div”);
div.innerHTML=x;
文件.正文.附件(div);
}
你很接近了。您需要学习如何正确使用,然后才能设置。get
不是一种承诺的方法,它只是一个正常的功能。听起来你想要Promise.all([get('a'),get('b')]),然后(function([aresult,bresult]){…})你能告诉我们你的“其他方式”吗?很难确定您真正想要的是什么,因为“加载多个URL”是微不足道的,而您错误的承诺示例也没有多大帮助。不应该loadMultiScript
只需附加到loadu queue
,将loadu cursor
重置为0
并开始第一个loadScript()
(让loadFinished
完成剩下的工作),而不是在一个循环中多次调用loadScript()
?这将并行加载每个,而不是按顺序加载。我想你应该阅读文章中的一章,你的linkedIt将导致“回调地狱”这不是回叫地狱,回叫地狱是做成功回叫里面的每一件事简洁的回答。谢谢much@defau1t-我又增加了两个选项。@jjfriend00不幸的是,我不能进行双重投票。但是谢谢though@defau1t-我添加了一种执行get(x).get(y).get(z)
的方法。
Promise.map(['a.json', 'b.json', 'c.json'], function(item) {
// do some operation on item and return data or a promise
return something;
}).then(function(results) {
// all done
}, function(err) {
// error here
});