1

the question is clear, I need to display an alert with the elements of a firebase list.

Alert creation

let alert = this.alertCtrl.create({
      title: 'Elegir repartidor',
      inputs: [],
      buttons: [
        {
          text: 'Asignar',
          handler: data => {
              this.firebaseService.updateOrderAssignDeliverymen(orderKey, data);
              },
          role: 'cancel'
        }
      ]
    });
    this.firebaseService.getDeliveryMenFillAlert(alert).then(res => alert.present());

Alert Inputs creation

getDeliveryMenFillAlert(alert: AlertController) {
    this.afd.list('/users', ref => ref.orderByChild('role').equalTo('Repartidor'))
      .snapshotChanges()
      .subscribe( res =>
        res.map(action => {
          alert.addInput({
            type: 'radio',
            label: action.payload.val().name,
            value: action.key
          })
        }),
        error => console.log(error));
  }

After reading many questions, quite surprised about the number of different approaches... and more surprised that I haven't been able to success with one.

First attempt

Created a second function with a simple promise return to try. Everything is working ok.

getDeliveryMenFillAlert2(alert: AlertController) {
return Promise.resolve(true);
//return Promise.reject(false);

}

this.firebaseService.getDeliveryMenFillAlert2(alert)
  .then(resolve => console.log('Resolve: ' + resolve),
        reject => console.log('Reject: ' + reject));

Second attempt

Tried to insert this simple return in my original function an of course change the call to this original function.

getDeliveryMenFillAlert(alert: AlertController) {
this.afd.list('/users', ref => ref.orderByChild('role').equalTo('Repartidor'))
  .snapshotChanges()
  .subscribe( res =>
    res.map(action => {
      alert.addInput({
        type: 'radio',
        label: action.payload.val().name,
        value: action.key
      });
      return Promise.resolve(true);
    }),
  error => {
    console.log(error)
    return Promise.reject(false);
  });

}

But an error is thrown "TypeError: Cannot read property 'then' of undefined".

Third attempt

Added return Promise to the function. Same error.

getDeliveryMenFillAlert(alert: AlertController): Promise {

Fourth attempt Reading one of the questions it introduced the async/await concept, so I introduced "async" to the function and "await" to the response.

async getDeliveryMenFillAlert(alert: AlertController): Promise {

return await Promise.resolve(true);

Recibe another error "Uncaught Error: Module parse failed: The keyword 'yield' is reserved".

Last try

Don't know why but just deleted "await" but keeping "async" in the function, it doesn't retrieve any error (great) but the console.log of the call prints "Resolve: undefined".

So it seems that is resolving but doesn't work.

I also tried to return "new Promise..." and "true.toPromise()" instead of "return Promise.resolve(true)", I read it somewhere but nothing is working. Any help please, I'm trying hard but not able to.

FINAL SOLUTION (can't post it as response)

getDeliveryMenFillAlert(alert: AlertController) {
    return new Promise(resolve => {
    this.afd.list('/users', ref => ref.orderByChild('role').equalTo('Repartidor'))
      .snapshotChanges()
      .subscribe( res =>
        res.map(action => {
          alert.addInput({
            type: 'radio',
            label: action.payload.val().name,
            value: action.key
          });
          resolve(alert);
        }))
      });
   }

and the call would be:

this.firebaseService.getDeliveryMenFillAlert2(alert)
      .then(resolve => alert.present());
Carlos
  • 23
  • 3

1 Answers1

1

I'm guessing you're calling alert.present() just after this call :

this.firebaseService.getDeliveryMenFillAlert(alert);

If so, you probably want to wait for your callback to end before displaying the alert.

  • A quick fix could be to present the alert after setting the inputs :
alert.addInput({
  type: 'radio',
  label: action.payload.val().name,
  value: action.key
});
alert.present();
  • But a better way would be to return a promise from your getDeliveryMenFillAlert function. And call alert.present() in the sucess callback :
this.firebaseService.getDeliveryMenFillAlert(alert)
    .then(res => alert.present());
Nicolas L
  • 305
  • 2
  • 7
  • First approach working (great) but as you recommend I want to use the better way. I guess that here I don't really need to return any data, so "res" is unuseful. Watching other questions to learn promises I have tried to return new Promise(true); return new Promise((res) => { res(true); }); But it's throwing the error "Cannot read property then of undefined", what should I return ¿? – Carlos Mar 13 '18 at 11:43
  • You should read [this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then) to learn about promises. [This thread](https://stackoverflow.com/a/39296015/9425100) explain how to deal with _observable_, instead of wrapping your function in a _promise_ as I suggested. – Nicolas L Mar 13 '18 at 12:32
  • Your link and many other questions and videos about promises already readen, will write an answer to give more details – Carlos Mar 14 '18 at 10:12