Asynchronous Chilkat Methods in Node.js

Chilkat implements a thread pool for asynchronous tasks in all programming languages except for Node.js. For Node.js, Chilkat tasks run directly on Node’s internal thread pool (i.e. the libuv thread pool). The Task.Run() method can have 0 or 1 arguments. If an argument is passed, it is the “task completed” callback that get called when the task has completed. Here is an example showing how to send email asynchronously using Chilkat in Node.js

var os = require('os');
if (os.platform() == 'win32') {  
    var chilkat = require('chilkat_win32'); 
} else if (os.platform() == 'linux') {
    if (os.arch() == 'x86') {
        var chilkat = require('chilkat_linux32');
    } else {
        var chilkat = require('chilkat_linux64');
    }
} else if (os.platform() == 'darwin') {
	var chilkat = require('chilkat_macosx');
}

// While a task is running, there are three standard callbacks that can be made (if desired).
// They are progressInfo, percentDone, and abortCheck.   These callbacks are made directly
// from the libuv worker thread.

// progressInfo callbacks have name/value string arguments.
// Experiment to see what information is provided for any given task.
function progressInfo(name, value) {
    console.log(name + ": " + value);
}

// The percentDone callback provides an integer percentage completion value, typically from 0 to 100.
// percentDone callbacks are made only in cases where it is possible to know a percentage completed.
// For example, establishing a socket or TLS connection will not have percentDone callbacks, because
// it makes no sense - a client simply waits until the server accepts the connection.  It's never in a state
// where it can be "50% done".
function percentDone(pctDone) {
    console.log("percent complete: " + pctDone);
    // Return true to cause the task to abort.
    // Return false to allow the task to continue.
    return false;	
}

// The abortCheck event is called periodically to allow the application to abort an asynchronous task.
function abortCheck() {
    console.log("abort check");
    // Return true to cause the task to abort.
    // Return false to allow the task to continue.
    return false;
}


// The taskCompleted event is called from the main Node.js thread.
function taskCompleted(task) {

    // Before looking at the task result, close the connection with the SMTP server..
    success = mailman.CloseSmtpConnection();
    if (success != true) {
        console.log("Connection to SMTP server not closed cleanly.");
    }

    //  A finished/completed task may be one that was canceled, aborted, or truly finished.
    //  If the task was "canceled", it was canceled prior to actually starting.  

    //  If the task "completed", then it ran to completion, but the actual success/failure of the method
    //  is determined by the result obtained via one of the GetResult* methods.  (A "completed" task will
    //  have a StatusInt equal to 7.   If the task finished, but was not completed, then it must've
    //  been aborted or canceled:
    if (task.StatusInt != 7) {
        console.log("Task did not complete.");
        console.log("task status: " + task.Status);
        return;
    }

    //  The SendEmail method returns a boolean.  Therefore, after the task is finished,
    //  we can get the boolean result by calling GetResultBool.  This is the return value had
    //  SendEmail been called synchronously.
    success = task.GetResultBool();
    if (success != true) {
        //  The task's ResultErrorText contains what would have been in the LastErrorText property had
        //  the SendEmail method been called synchronously.
        console.log(task.ResultErrorText);
    }
    else {
        console.log("Email sent asynchronously.");
    }
}


function chilkatExample() {

    //  All Chilkat classes can be unlocked at once at the beginning of a program
    //  by calling UnlockBundle.  It requires a Bundle unlock code.
    var chilkatGlob = new chilkat.Global();
    var success = chilkatGlob.UnlockBundle("Anything for 30-day trial.");
    if (success != true) {
        console.log(chilkatGlob.LastErrorText);
        return;
    }

    var mailman = new chilkat.MailMan();

    //  Set the SMTP server and any required settings.
    mailman.SmtpHost = "smtp.mymailserver.com";
    mailman.SmtpUsername = "myLogin";
    mailman.SmtpPassword = "myPassword";
    mailman.StartTLS = true;

    //  Create a new email object
    var email = new chilkat.Email();

    email.Subject = "This is a test";
    email.Body = "This is a test";
    email.From = "Chilkat Support <support@chilkatsoft.com>";
    success = email.AddTo("Chilkat Admin","admin@chilkatsoft.com");

    //  Call the async version of the SendEmail method to return a task object.
    //  The task object is loaded, but is in the Inert state -- meaning it is
    //  not yet scheduled to run on Node's libuv thread pool.
    var task = mailman.SendEmailAsync(email);
    if (task == null ) {
        console.log(mailman.LastErrorText);
        return;
    }

    // Hookup callbacks that are called while the task is running.
    // Notice that these are on the mailman object, not on the Task object.
    mailman.ProgressInfo = progressInfo;
    mailman.PercentDone = percentDone;
    mailman.AbortCheck = abortCheck;

    //  Schedule the task for running on Node's thread pool.  This changes the task's state
    //  from Inert to Live.
    // Pass the taskCompleted function so that it runs asynchronously.
    // If no arguments are passed to task.Run(), then it runs synchronously (following Node's conventions).
    success = task.Run(taskCompleted);
    if (success != true) {
        console.log(task.LastErrorText);
        return;
    }

    //  The application continues while the email is being sent in one of Node's worker threads.
}

chilkatExample();