Mappare funzione asincrona di pacchetto Node.Js

Se devo utilizzare un pacchetto di Node.js che non è incluso in quelli presenti su Instant Developer Cloud lo devo importare utilizzando require(), previa aver caricato il pacchetto nel server ide e di produzione nei quel voglio utilizzare l’applicazione web, e poi utilizzare le funzioni che mi servono.

Come si aggiunge un pacchetto Node.js è descritto nel manuale Integrazione di componenti esterni.

Fino a qui nulla di strano, ma se il metodo che devo utilizzare è asincrono?
Come faccio a ricondurlo all’utilizzo di una funzione asincrona mediante yield come per quelli già presenti?

Vediamo insieme un esempio su un metodo già esistente come app.sleep(), così non dovete importare un pacchetto specifico di Node.js per provare questo codice (è possibile anche provare sul server di Community nel quale non potete modificare i pacchetti installati).

Per prima cosa ho definito una libreria di tipo Personalizzata (MyLib) in cui ho metterò il mio codice.
Al suo interno ho creato la classe MyUtils con due metodi:

  • mySleep - questa è la funzione che va usata nel proprio codice
  • mySleepAsync - questa è la funzione richiamata da mySleep che esegue l’operazione

Questo il codice di mySleep:

App.MyLib.MyUtils.prototype.mySleep = function(sleepTime, par2)
{
  // Faccio in modo che il sistema veda il metodo "mySleep" come asincrono
  yield app.sleep(0);
  //
  // Uso una variabile locale per fare in modo che il metodo "mySleepAsync" sia referenziato nel codice
  let funct = this.mySleepAsync;
  //
  // Chiamo la versione "Async" del metodo usando apply per evitare che il sistema tolga "yield" non conoscendo la funzione "funct".
  return yield funct.apply(this, [sleepTime, par2, __resumer]);
};

L’oggetto __resumer è la callback della funzione.
l’istruzione yield app.sleep(0); serve a forzare l’ide nel cosiderare il metodo asincrono.

Questo il codice di mySleepAsync:

App.MyLib.MyUtils.prototype.mySleepAsync = function(sleepTime, par2, callback)
{
  app.sleep(sleepTime, function (result, error) {
    callback(sleepTime % 2 === 0);
  });
};

In questa funzione mi sono inventato un valore di ritorno in quanto app.sleep() non ritorna nulla.

Come utilizzo poi la mia funzione? Molto semplice:

  let mu = new App.MyLib.MyUtils(app);
  yield mu.mySleep(1000);

Istanzio la mia classe e richiamo il metodo sull’istanza.
Quindi io scrivo mu.mySleep(1000) e ci pensa l’ide a mettere yield.

In questo modo le funzioni si richiamano come quelle già definite nel frame work.

Che ne dite vi piace?
Qualcuno ha fatto di meglio?

5 Mi Piace

Ottimo, ho integrato nodemailer e ha funzionato.

1 Mi Piace

@cioffi.m mi fa piacere che ti sia stato utile.

Se vuoi puoi spiegare in un tuo post come integrare nodemailer.

Certo.

Ho importato il pacchetto npm: nodemailer@7.0.12

In una libreria di tipo Personalizzata ho creato le 2 funzioni:

App.WndFnc.SyncCall.prototype.sendGmail = function(options)
{
  yield app.sleep(0);
  let funct = this.mySendGmail;
  return yield funct.apply(this, [options, __resumer]);
};

App.WndFnc.SyncCall.prototype.mySendGmail = function(options, callback)
{
  const nodemailer = require("nodemailer");
  let key = app.getParameter("gmail-key");
  let from = app.getParameter("gmail-from");
  const params = {
    service : "gmail",
    auth : {
      user : from,
      pass : key,
    },
  };
  const transporter = nodemailer.createTransport(params);
  transporter.sendMail(options)
    .then((info) => {
      if (app.inPreview()) {
        console.log(info);
      }
      callback("OK");
    })
    .catch ((error) => {
      console.error("SEND MAIL ERROR:", error.message);
      callback(error.message);
    });
};

Per inviare:

  // Email options
  const mailOptions = {
   from : {name : fromName, address : fromAddress},
   to : mailTo,
   subject : mailSubject,
   html : "<h1>Ciao!</h1><p>Questo è il contenuto HTML</p>",
  };

  let syncCall = new App.WndFnc.SyncCall(app);
  const ret = yield syncCall.sendGmail(mailOptions);
2 Mi Piace

Grazie della condivisione @cioffi.m :+1: