Búsqueda de sitios web

angular - Ejecutar código después de ejecutar todo el bucle for


Por favor, avísame si tengo que proporcionar más código o explicaciones.

Estoy intentando ejecutar validate, si la validación no es exitosa, confirm(Yes/No), y luego guardar el método para todas las filas seleccionadas en un bucle for.

Requisito: Debo mostrar un mensaje de éxito/fracaso después de recorrer todas las filas seleccionadas. Eso significa:

Si se seleccionan 5 filas (2 son válidas y 3 no son válidas) - obtenido de myService.validate

Preguntará si aún deseas continuar con 3 registros no válidos - myConfirmService.confirm

Debería guardar esos 2 registros válidos

Si el usuario selecciona 'Sí' en la ventana de confirmación (digamos para 2 registros), entonces también debería guardar estos 2.

Al final, mostrará un mensaje de éxito/fracaso - alertService.success

Lo que quiero:

Para cumplir con lo que describí en el requisito

y el mensaje de éxito/fracaso debería mostrarse solo una vez después de que se guarden todos los registros

component.ts:

save() {
    this.selectRowData.forEach(async s => {
        this.myService.validate(s.id).subscribe(data => {
            console.log(data);
            if(data == false) {
                this.myConfirmService
                    .confirm('Please confirm..', 'Selected Part do not match expected part data. \n Do you still want to continue? ', 'Yes', 'No')
                    .then((confirmed) => {
                        if(confirmed) {
                            console.log("User selected: Yes");
                            this.myService.savePart();
                        } else {
                            console.log("User selected: No");
                        }
                    })
                    .catch(() => {
                        console.log("Error...");
                    });
            } else {
                console.log("Selected Rule matches expected rules for: " + s.designChangeClass);
                this.saveModelPart(s);
            }
        }, (error: any) => {
            alert("Error Linking Lot");
        });
    });
    console.log('1st After for loop');
    this.alertService.success('Part saved successfully.')
}

service.ts

validate(id: string): Observable < boolean > {
    return this.httpClient.get < boolean > ('/RestWeb/validate?id=' + id);
}
      
validate1(id: string) {
    return this.httpClient.get < boolean > ('/RestWeb/validate?id=' + id).toPromise();
}
  
savePart(item: Part): Observable<any> {
    return this.httpClient.post('/RestService/savePart', item);
}

Respuesta #1

Aquí tienes.

//Change method to async
async save() {
  //Create custom index variable, since for of loop doesn't have one
  let ind = 0;
  //Use for of instead of forEach
  for (const eachRow of this.selectRowData) {
    //await until API validated
    const isValid = await this.myService.validate(eachRow.id).toPromise();
    if (!isValid) {
      //await again if it is not valid and until user confirmed
      const isConfirmed = await this.myConfirmService.confirm('Please confirm..', 'Selected Part do not match expected part data. \n Do you still want to continue? ', 'Yes', 'No').toPromise();
      if (isConfirmed) {
        //await again until record saved as user selected yes in confirm
        console.log('User selected: Yes');
        await this.myService.savePart().toPromise();
      } else {
        console.log('User selected: No');
      }
    } else {
      console.log(
        'Selected Rule matches expected rules for: ' +
          eachRow.designChangeClass
      );
      this.saveModelPart(eachRow);
    }
    //Finally display message after loop is finished
    if (ind === this.selectRowData.length - 1) {
      this.alertService.success('Part saved successfully.');
    }
    ind++;
  }
}

Aunque esta solución funciona, no es una buena práctica hacerlo de esta manera.
En su lugar, modifique la API para aceptar múltiples ids para validación y muestre una tabla de registros (éxitos y fallos) junto con botones para confirmar la continuación.

Respuesta #2

Podrías usar fork join en este caso, así realiza todas las llamadas y obtiene la respuesta en un arreglo de booleanos

save() {
  let obsArray = this.selectRowData.map(s=>this.myService.validate(s.id));
  forkJoin(obsArray).subscribe(
    (arrayBoolean)=>{
       // do your logic here
    }
  )
 
}

Consulta https://www.learnrxjs.io/learn-rxjs/operators/combination/forkjoin para más información

//EDITAR: escrito incorrectamente

Artículos relacionados