mouchin777
mouchin777

Reputation: 1588

How to stop a js promise.all() on a condition?

I have this piece of code

 let promiseList = []

    for (let i in data) {
        let promise = checkIfMember(data[i].tg_id, chatId).then(res => {
            if (res) {
                //if the user has a undefined username it won't be rained
                if (data[i].username != "undefined") {
                    console.log(data[i].username)
                    members.push([data[i].tg_id, data[i].username])
                }
            }
        }).catch(err => {
            console.log(err)
        })
        promiseList.push(promise)
    }

    return Promise.all(promiseList).then((res) => {
        //list of members that are in the room , we randomize it before returning
        shuffleArray(members)
        if(numberOfUsers > members.length){
            return[false, members.length]
        }else{
            members = members.slice(0,numberOfUsers)
            return [true, members]
        }
    });

Basically I have a promise list that is being filled. And then all of them are executed with a promiseAll. The problem is that I dont want all of them to execute, I want to to do something like this:

let promiseList = []
    let validmembers = 0;
    for (let i in data) {
        let promise = checkIfMember(data[i].tg_id, chatId).then(res => {
            if (res) {
                //if the user has a undefined username it won't be rained
                if (data[i].username != "undefined") {
                    console.log(data[i].username)
                    members.push([data[i].tg_id, data[i].username])
                    //stop there the execution
                    validmembers++;
                    if(validmembers == numberOfUsers){
                        return;
                    }
                }
            }
        }).catch(err => {
            console.log(err)
        })
        promiseList.push(promise)
    }

    return Promise.all(promiseList).then((res) => {
        //list of members that are in the room , we randomize it before returning
        shuffleArray(members)
        if(numberOfUsers > members.length){
            return[false, members.length]
        }else{
            members = members.slice(0,numberOfUsers)
            return [true, members]
        }
    });

But the problem is that the promises are async, so the promiselist filling doesnt stop. How would I solve this?

Upvotes: 0

Views: 610

Answers (1)

Always Learning
Always Learning

Reputation: 5581

It appears you want the members array to have no more than numberOfUsers entries in it due to the promises. Since the promises run asynchronously you can't stop the checkIfMember function from being called, but inside of its then function you could avoid accumulating more members like this:

// don't use `!== "undefined"` unless it can actually be the string "undefined"
if (data[i].username) {  
  if (members.length < numberOfUsers) {
    console.log(data[i].username);
    members.push([data[i].tg_id, data[i].username]);
  }
}

By only pushing to members when it's not yet full you will avoid adding more than numberOfUsers and don't need to do the slice later.

If instead you want to avoid the entire promise work when enough have been collected, then you can serialize them like this:

async function yourFunction() {
  for (let i in data) {
    if (members.length < numberOfUsers) {
      // don't continue to the next 'i' until this one is done
      await checkIfMember(data[i].tg_id, chatId)
        .then(res => {
          if (res) {
            //if the user has a undefined username it won't be rained
            if (data[i].username != "undefined") {
              console.log(data[i].username);
              members.push([data[i].tg_id, data[i].username]);
            }
          }
        })
        .catch(err => {
          console.log(err);
        });
    } else {
      break; // no need to continue once members is full 
    }
  }

  return [true, members];
}

Upvotes: 1

Related Questions