ditesh / node-poplib

POP3 client library for Node.js
MIT License
128 stars 44 forks source link

Implement promise-based api #29

Open Masterxilo opened 6 years ago

Masterxilo commented 6 years ago

Installing event handlers for each individual api call feels very unnatural.

Fr0sT-Brutal commented 5 years ago

I implemented promisifying, seems working

function promisifyPOP3Client(client)
{
    const commands = ['connect', 'login', 'auth', 'apop', 'stls', 'top', 'list', 'stat', 'uidl',
       'retr', 'dele', 'noop', 'rset', 'capa', 'quit'];
    const intCmdPrefix = '_int_';

    for (let cmd of commands)
    {
        // rename old command method
        // 'connect' only has event and not method so check if method exists
        if (client[cmd])
            client[intCmdPrefix + cmd] = client[cmd];
        // set new methods that return Promise
        client[cmd] = function (...commandArgs)
        {
            return new Promise(
                function (resolve, reject)
                {
                    client.once(cmd, function (status, ...args)
                        {
                            if (status === false)
                                reject(new Error(`Command ${cmd} failed`));
                            else
                                resolve(args);
                        });

                    client.once('error', function(err)
                        {
                            if (err.errno === 111) reject(new Error('Unable to connect to server'));
                            else reject(err);
                        });

                    client.once('invalid-state', function(cmd)
                        {
                            reject(new Error('Invalid state. You tried calling ' + cmd));
                        });

                    client.once('locked', function(cmd)
                        {
                            reject(new Error('Current cmd has not finished yet. You tried calling ' + cmd));
                        });

                    if (client[intCmdPrefix + cmd])
                        client[intCmdPrefix + cmd](...commandArgs);
                });
        }
    }
}

Sample:

    const client = new POP3Client(options.port, options.host,
        {
            debug: options.debug,
            enabletls: options.tls
        });

    promisifyPOP3Client(client);

    await client.connect();
    await client.login(options.username, options.password);
    const uidlRes = await client.uidl(); // msgnumber, data, rawdata
    ...
    await client.quit();
Masterxilo commented 5 years ago

@Fr0sT-Brutal amazing job! That‘s something i can work with.

Fr0sT-Brutal commented 5 years ago

@Masterxilo you're welcome! Feel free to suggest improvements/optimizations, I'm currently quite new to Promise stuff :)

advayumare commented 2 years ago

@Fr0sT-Brutal Amazing man. Saved me a lot of time. Thanks and upvote to include this in the package itself.