1

I am currently trying to extend the standard Error class of javascript for process issues, more precisely, I want to check FTP data while throwing my customError. The problem is that it never waits the await function to finish before throwing. The awaited function return a promise as well.

So far as I am, I have this sample code for my class, note that remoteFs is just a custom module containing my functions to manipulate remote FTP data.

module.exports = class processError extends Error {

    constructor(args) {
        super(args);

        this.name = "customError"
        this._folder = "./test/"
        this._credentials = {
                host: 'my.host.com',
                user: 'username',
                password: 'passwd123',
            }

        return (this._errorProcess());
    }

    async _errorProcess () {

        try {
            // The function below is basic FTP list and should return a promised true/false if the folder exists or not.
            let IsThereFolder = await remoteFs.EntityExist(this._credentials, this._folder)
        } catch (err) {
            throw new Error("Fatal error in error handler:", err)
        }

        console.log("Should I create folder ?", IsThereFolder )
        return (this);
    }
}

I tried several methods to make the constructor wait, like calling _errorProcess from an init() function that would return it after being called from constructor. I also tried to put this function out the class scope but nothing seems to work properly, I always end up having the throwing output before receiving my promise.

module.exports = {

EntityExist: function (credentials, toFind) {
       var c = new Client();
       let entityExist = false;

       return new Promise((resolve, reject) => {
           console.log("CREDENTIALS ->", credentials)
           c.on('ready', function () {
               console.log("Connection established");
               c.on('error', function (err) {
                   console.log(err);
                   reject(err);
               })
               c.list(toFind, (err, list) => {
                   if (err) throw err;

                   for (let i = 0; i < list.length; i++) {
                       if (list[i].name == toFind) { entityExist = true; }
                   }
                   c.on('end', () => { resolve(entityExist); })
                   c.end();
               });
           });
           console.log("Before connect")
           c.connect(credentials);
       })
   }
};

And here is the actual output I get for this execution:

CREDENTIALS -> { host: 'my.host.com',                                                       
  user: 'username',                                                                                    
  password: 'passwd123' }                                                                                  
Before connect                                                                                          

C:\path_to_project\includes\file.js:62 
                        throw new handleError("Testing custom error: " + err); break;    
                        ^                                                                               
[object Promise]

npm ERR! code ELIFECYCLE
npm ERR! errno 1
(...)

So as you can see, it doesn't wait for the promise to came back and don't even reach the "Connection established" log on the EntityExist function (please not that this function works fine in another circonstances).

Actually, I don't even know if it's possible to perform such things directly from constructor. I hope the context is clear enough, thanks for your time!

1 Answers1

0

The await operator is used to wait for a Promise. It can only be used inside an async function.

It means you cannot use in global scope or in class constructor.

The constructor using a promise is a bad practice because you will not be able to get the class as well (link to another stackoverflow answer).

You technically could return a Promise from a constructor but this is not his purpose.

With your case, you can use a function before calling a throw, that's not beautiful but it does the job.

As:

async generateAsyncError(asyncFn) {
  await asyncFn();

  throw new Error();
}

Here you can use async before throwing an error. But keep in mind that the error will not be throw before the async function will be completed.

Liroo Pierre
  • 875
  • 2
  • 9
  • 25