Javascript - 如何等待事件侦听器结束下一次迭代

时间:2018-02-13 13:29:58

标签: javascript

我在for循环中面临一个事件监听器的问题。

基本上我有这个:

for (var i = 0; i < 2; i++) {
  
  //window url change here, each iteration open a different url
  console.log('what??');

  window.addEventListener('load', aperture, true);

  function aperture() {
    console.log('here');
    window.close();
  }
}

所以,我必须等待窗口加载才能执行该函数,然后转到下一步进行迭代并执行相同的操作。但是我看到这个日志的原因是:

    what??
    what??
    here
    here

如何在迭代之间等待事件监听器完成?

1 个答案:

答案 0 :(得分:0)

我只会回答你实际问过的问题......

  

如何在迭代之间等待事件监听器完成?

你不能用真正的循环来实现它,制作异步“循环”的唯一方法是使用递归,这可能会稍微复杂一些。我们的想法是创建一个函数,在它准备好再次迭代时调用它自己。

(function myLoop(){
  
  // do something that takes a while
  setTimeout(function(){
     console.log("did something");
     
     // then recurse...
     myLoop();
     
  }, 1500);
  
})();

如果你在一个数组上循环,那么这个概念是类似的...这是我写的general purpose function做的事情......

var myArray = ["a","b","c","d"];
var myLoop = slowLoop(myArray, (itm, idx, cb)=>{
    
    setTimeout(()=>{
        console.log(`doing something with ${itm} which is item number ${idx} in the array`);
        
        // call cb when finished
        cb();
        
    }, 1000);
    
});

// when it's done....
myLoop.then(()=>{

    console.log("All done looping");

});


/**
 * Execute the loopBody function once for each item in the items array, 
 * waiting for the done function (which is passed into the loopBody function)
 * to be called before proceeding to the next item in the array.
 * @param {Array} items - The array of items to iterate through
 * @param {Function} loopBody - A function to execute on each item in the array.
 *		This function is passed 3 arguments - 
 *			1. The item in the current iteration,
 *			2. The index of the item in the array,
 *			3. A function to be called when the iteration may continue.
 * @returns {Promise} - A promise that is resolved when all the items in the 
 *		in the array have been iterated through.
 */
function slowLoop(items, loopBody) {
	return new Promise(f => {
		done = arguments[2] || f;
		idx = arguments[3] || 0;
		let cb = items[idx + 1] ? () => slowLoop(items, loopBody, done, idx + 1) : done;
		loopBody(items[idx], idx, cb);
	});
}