Search code examples
javascriptnode.jsecmascript-6promisees6-promise

How can I break out of this Promise for loop?


EDIT: I know how to get it working using async/await but unfortunately, I can't use it as it's not widely supported (especially iOS 10, Internet Explorers etc). So I need a promises only way.

I am very new to Promises so I am stuck. I have this for loop which I want to break out of whenever i equals to 2 (just for example). I have tried putting the reject but it still continues on until i<10. I want it to stop when my condition is met.

for (let i = 0, p = Promise.resolve(); i < 10; i++) {
  p = p.then(_ => new Promise((resolve, reject) => {
    setTimeout(function() {
      console.log(i);
      if (i == 2) {
        reject("BREAK HERE");
      } else {
        resolve();
      }
    }, Math.random() * 1000)
  })).catch(err => {
    console.log(err);
  });
}

Current output:

0
1
2
BREAK HERE
3
4
5
6
7
8
9

I want it to just be:

0
1
2
BREAK HERE

Solution

  • Just dont resolve and the sequence will stop

    for (let i = 0, p = Promise.resolve(); i < 10; i++) {
      p = p.then(_ => new Promise((resolve, reject) => {
        setTimeout(function() {
          console.log("i",i);
          if (i == 2) {
            console.log("break here")
            
          } else {
            resolve();
          }
        }, Math.random() * 1000)
      })).catch(err => {
        console.log("err",err);
      });
    }

    But as this code itself intents to sequence async calls one should think about doing so:

    // repeated call
    next(
      0/*state*/, 
      i=>i<2/*match*/, 
      i=>i+1/*increment*/,     
      asyncCallPromisefied/*promise|promise[]*/, 
      [0]/*args*/
    )
    .catch(console.log)
    
    
    // traverse array
    next(
      0/*state*/, 
      i => i < 6/*match*/, 
      i => i + 1/*increment*/,
      asyncChain()/*promise|promise[]*/, 
      [0]/*args*/,
      0/*[promise[] index]*/
    )
    .catch(console.log)
    
    
    // helper
    function next(state, match, increment, action, args, pointer = 0/**inactive**/){
      if(match(state))
      if(Array.isArray(action)){
         
         return pointer < action.length
          ? action[pointer](...args)
          .then(i => next(
            increment(state), 
            match, 
            increment, 
            action, 
            [i],
            pointer + 1
          ))
          : undefined;
      } else {
        return action(...args)
        .then(i => next(
          increment(state), 
          match, 
          increment, 
          action, 
          [i]
        ))
      }
    }
    
    
    
    // wrapper
    function asyncCall(i, callback){ 
      return setTimeout(() => {
        console.log(i == 2 ? 'break here': i);
        callback(null, ++i);
      }, Math.random() * 1000)
    }
    
    function asyncCallPromisefied(i){
      return new Promise(function(resolve, reject){
        asyncCall(i, function(err, args){
          if(err){
            reject(err)
          } else {
            resolve(args)
          }
        })
      })
    }
    
    function asyncChain(){return [
      function(i){console.log("chain",i);return Promise.resolve(i)},
      function(i){console.log("chain",i);return Promise.resolve(i)},
     function(i){console.log("chain",i);return Promise.resolve(i)},
      asyncCallPromisefied,
      function(i){console.log("chain",i);return Promise.resolve(i)},
    ]}