目标:循环遍历一段时间的网址,让他们使用postMessage完全加载以确定何时完成(某些页面需要很长时间)
实现了这一点,但它的工作不正常:jquery deferred in for loop
实现了这个,并且它正在工作,但不在循环中,因为javascript只打开最后一个窗口:http://davidwalsh.name/window-postmessage
function scrape(url){
var deferred = new $.Deferred();
var myPopUp = window.open(url,'myWindow');
setInterval(function(){
var message = 'Hello! The time is: ' + (new Date().getTime());
console.log('Scraper Launcher: sending message: ' + message);
myPopUp.postMessage(message,domain);//send the message and target URI
},6000);
//listen to holla back
window.addEventListener('message',function(event) {
if(event.origin !== domain) return;
console.log('received response: ',event.data);
if(event.data == 'You were successful!'){
console.log('closing child window');
myPopUp.close();
deferred.resolve('Success');
}else{
console.log('oh dear, FAILURE: ' + urls[i]);
deferred.resolve('Failure');
}
},false);
return deferred.promise();
}
var urls = [domain +"/url1",domain +"/url2"];
$("#launch_windows").click(function(){
console.log('launching');
for (i = 0; i < urls.length; i++) {
(function(i){
console.log('NOW i is ' + i + ' and url is ' + urls[i]);
$.when(scrape(urls[i])).then(function(results){
console.log('DONE (' + results + ')with ' + urls[i]);
});
})(i);
}
});
如果这是完全可怕的逻辑和代码,我很乐意接受建议。
答案 0 :(得分:7)
我喜欢通过创建解析的$ .Deferred,添加到链,并在每次迭代时将延迟的值分配给新的promise来解决这些问题(异步操作的顺序循环)。
$("#launch_windows").click(function(){
console.log("launching");
var dfd = $.Deferred().resolve();
for(i = 0; i < urls.length; i++){
(function(i){
dfd = dfd.then(function(){
return scrape(urls[i]);
}).then(function(results){
console.log("results: "+results);
});
})(i);
}
});
使用forEach而非IIFE提供封闭的清洁版:
var dfd = $.Deferred().resolve();
urls.forEach(function(url){
dfd = dfd.then(function(){
return scrape(url);
}).then(function(results){
console.log("results: "+results);
});
});
您的问题在每次迭代中都在$.when
中。在第一次迭代$.when
创建了一个新的promise(由于scrape返回一个promise而不必要的btw),然后添加了一个then
来处理结果。在下一次迭代中,未引用此原始承诺,并为下一个url创建新的承诺(在第一次完成刮擦之前!)等等。
此解决方案将所有异步操作保存在同一个$ .Deferred链中,按顺序执行它们(您想要的)。
你确实得到使用IIFE来冻结i值的分数!
继承人jsFiddle