@@ -243,7 +243,9 @@ be safely released.
243243Note that ` Napi::AsyncProgressWorker::ExecutionProcess::Send ` merely guarantees
244244** eventual** invocation of ` Napi::AsyncProgressWorker::OnProgress ` , which means
245245multiple send might be coalesced into single invocation of ` Napi::AsyncProgressWorker::OnProgress `
246- with latest data.
246+ with latest data. If you would like to guarantee that there is one invocation of
247+ ` OnProgress ` for every ` Send ` call, you should use the ` Napi::AsyncProgressQueueWorker `
248+ class instead which is documented further down this page.
247249
248250``` cpp
249251void Napi::AsyncProgressWorker::ExecutionProcess::Send (const T* data, size_t count) const;
@@ -269,7 +271,8 @@ function runs in the background out of the **event loop** thread and at the end
269271the `Napi::AsyncProgressWorker::OnOK` or `Napi::AsyncProgressWorker::OnError` function will be
270272called and are executed as part of the event loop.
271273
272- The code below shows a basic example of the `Napi::AsyncProgressWorker` implementation:
274+ The code below shows a basic example of the `Napi::AsyncProgressWorker` implementation along with an
275+ example of how the counterpart in Javascript would appear:
273276
274277```cpp
275278#include <napi.h>
@@ -281,28 +284,38 @@ using namespace Napi;
281284
282285class EchoWorker : public AsyncProgressWorker<uint32_t> {
283286 public:
284- EchoWorker(Function& callback , std::string& echo)
285- : AsyncProgressWorker(callback ), echo(echo) {}
287+ EchoWorker(Function& okCallback , std::string& echo)
288+ : AsyncProgressWorker(okCallback ), echo(echo) {}
286289
287290 ~EchoWorker() {}
288- // This code will be executed on the worker thread
289- void Execute(const ExecutionProgress& progress) {
290- // Need to simulate cpu heavy task
291- for (uint32_t i = 0; i < 100; ++i) {
292- progress.Send(&i, 1)
293- std::this_thread::sleep_for(std::chrono::seconds(1));
291+
292+ // This code will be executed on the worker thread
293+ void Execute(const ExecutionProgress& progress) {
294+ // Need to simulate cpu heavy task
295+ // Note: This Send() call is not guaranteed to trigger an equal
296+ // number of OnProgress calls (read documentation above for more info)
297+ for (uint32_t i = 0; i < 100; ++i) {
298+ progress.Send(&i, 1)
299+ }
300+ }
301+
302+ void OnError(const Error &e) {
303+ HandleScope scope(Env());
304+ // Pass error onto JS, no data for other parameters
305+ Callback().Call({String::New(Env(), e.Message())});
294306 }
295- }
296307
297- void OnOK() {
298- HandleScope scope(Env());
299- Callback().Call({Env().Null(), String::New(Env(), echo)});
300- }
308+ void OnOK() {
309+ HandleScope scope(Env());
310+ // Pass no error, give back original data
311+ Callback().Call({Env().Null(), String::New(Env(), echo)});
312+ }
301313
302- void OnProgress(const uint32_t* data, size_t /* count */) {
303- HandleScope scope(Env());
304- Callback().Call({Env().Null(), Env().Null(), Number::New(Env(), *data)});
305- }
314+ void OnProgress(const uint32_t* data, size_t /* count */) {
315+ HandleScope scope(Env());
316+ // Pass no error, no echo data, but do pass on the progress data
317+ Callback().Call({Env().Null(), Env().Null(), Number::New(Env(), *data)});
318+ }
306319
307320 private:
308321 std::string echo;
@@ -327,12 +340,23 @@ using namespace Napi;
327340
328341Value Echo (const CallbackInfo& info) {
329342 // We need to validate the arguments here
330- Function cb = info[ 1] .As<Function >();
331343 std::string in = info[ 0] .As<String >();
344+ Function cb = info[ 1] .As<Function >();
332345 EchoWorker* wk = new EchoWorker(cb, in);
333346 wk->Queue();
334347 return info.Env().Undefined();
335348}
349+
350+ // Register the native method for JS to access
351+ Object Init(Env env, Object exports)
352+ {
353+ exports.Set(String::New(env, "echo"), Function::New(env, Echo));
354+
355+ return exports;
356+ }
357+
358+ // Register our native addon
359+ NODE_API_MODULE(nativeAddon, Init)
336360```
337361
338362The implementation of a `Napi::AsyncProgressWorker` can be used by creating a
@@ -341,6 +365,20 @@ asynchronous task ends and other data needed for the computation. Once created,
341365the only other action needed is to call the `Napi::AsyncProgressWorker::Queue`
342366method that will queue the created worker for execution.
343367
368+ Lastly, the following Javascript (ES6+) code would be associated the above example:
369+
370+ ```js
371+ const { nativeAddon } = require('binding.node');
372+
373+ const exampleCallback = (errorResponse, okResponse, progressData) => {
374+ // Use the data accordingly
375+ // ...
376+ };
377+
378+ // Call our native addon with the paramters of a string and a function
379+ nativeAddon.echo("example", exampleCallback);
380+ ```
381+
344382# AsyncProgressQueueWorker
345383
346384` Napi::AsyncProgressQueueWorker ` acts exactly like ` Napi::AsyncProgressWorker `
@@ -379,7 +417,9 @@ void Napi::AsyncProgressQueueWorker::ExecutionProcess::Send(const T* data, size_
379417
380418## Example
381419
382- The code below shows a basic example of the ` Napi::AsyncProgressQueueWorker ` implementation:
420+ The code below show an example of the `Napi::AsyncProgressQueueWorker` implementation, but
421+ also demonsrates how to use multiple `Napi::Function`'s if you wish to provide multiple
422+ callback functions for more object oriented code:
383423
384424```cpp
385425#include <napi.h>
@@ -391,31 +431,55 @@ using namespace Napi;
391431
392432class EchoWorker : public AsyncProgressQueueWorker<uint32_t> {
393433 public:
394- EchoWorker(Function& callback, std::string& echo)
395- : AsyncProgressQueueWorker(callback), echo(echo) {}
434+ EchoWorker(Function& okCallback, Function& errorCallback, Function& progressCallback, std::string& echo)
435+ : AsyncProgressQueueWorker(okCallback), echo(echo) {
436+ // Set our function references to use them below
437+ this->errorCallback.Reset(errorCallback, 1);
438+ this->progressCallback.Reset(progressCallback, 1);
439+ }
396440
397441 ~EchoWorker() {}
398- // This code will be executed on the worker thread
399- void Execute(const ExecutionProgress& progress) {
400- // Need to simulate cpu heavy task
401- for (uint32_t i = 0; i < 100; ++i) {
402- progress.Send(&i, 1);
403- std::this_thread::sleep_for(std::chrono::seconds(1));
442+
443+ // This code will be executed on the worker thread
444+ void Execute(const ExecutionProgress& progress) {
445+ // Need to simulate cpu heavy task to demonstrate that
446+ // every call to Send() will trigger an OnProgress function call
447+ for (uint32_t i = 0; i < 100; ++i) {
448+ progress.Send(&i, 1);
449+ }
404450 }
405- }
406451
407- void OnOK() {
408- HandleScope scope(Env());
409- Callback().Call({Env().Null(), String::New(Env(), echo)});
410- }
452+ void OnOK() {
453+ HandleScope scope(Env());
454+ // Call our onOkCallback in javascript with the data we were given originally
455+ Callback().Call({String::New(Env(), echo)});
456+ }
457+
458+ void OnError(const Error &e) {
459+ HandleScope scope(Env());
460+
461+ // We call our callback provided in the constructor with 2 parameters
462+ if (!this->errorCallback.IsEmpty()) {
463+ // Call our onErrorCallback in javascript with the error message
464+ this->errorCallback.Call(Receiver().Value(), {String::New(Env(), e.Message())});
465+ }
466+ }
411467
412- void OnProgress(const uint32_t* data, size_t /* count */) {
413- HandleScope scope(Env());
414- Callback().Call({Env().Null(), Env().Null(), Number::New(Env(), *data)});
415- }
468+ void OnProgress(const uint32_t* data, size_t /* count */) {
469+ HandleScope scope(Env());
470+
471+ if (!this->progressCallback.IsEmpty()) {
472+ // Call our onProgressCallback in javascript with each integer from 0 to 99 (inclusive)
473+ // as this function is triggered from the above Send() calls
474+ this->progressCallback.Call(Receiver().Value(), {Number::New(Env(), *data)});
475+ }
476+ }
416477
417478 private:
418479 std::string echo;
480+ FunctionReference progressCallback;
481+ FunctionReference errorCallback;
482+
419483};
420484```
421485
@@ -439,12 +503,25 @@ using namespace Napi;
439503
440504Value Echo (const CallbackInfo& info) {
441505 // We need to validate the arguments here.
442- Function cb = info[1].As<Function>();
443506 std::string in = info[ 0] .As<String >();
444- EchoWorker* wk = new EchoWorker(cb, in);
507+ Function errorCb = info[ 1] .As<Function >();
508+ Function okCb = info[ 2] .As<Function >();
509+ Function progressCb = info[ 3] .As<Function >();
510+ EchoWorker* wk = new EchoWorker(okCb, errorCb, progressCb, in);
445511 wk->Queue();
446512 return info.Env().Undefined();
447513}
514+
515+ // Register the native method for JS to access
516+ Object Init(Env env, Object exports)
517+ {
518+ exports.Set(String::New(env, "echo"), Function::New(env, Echo));
519+
520+ return exports;
521+ }
522+
523+ // Register our native addon
524+ NODE_API_MODULE(nativeAddon, Init)
448525```
449526
450527The implementation of a `Napi::AsyncProgressQueueWorker` can be used by creating a
@@ -453,4 +530,28 @@ asynchronous task ends and other data needed for the computation. Once created,
453530the only other action needed is to call the `Napi::AsyncProgressQueueWorker::Queue`
454531method that will queue the created worker for execution.
455532
533+ Lastly, the following Javascript (ES6+) code would be associated the above example:
534+
535+ ```js
536+ const { nativeAddon } = require('binding.node');
537+
538+ const onErrorCallback = (msg) => {
539+ // Use the data accordingly
540+ // ...
541+ };
542+
543+ const onOkCallback = (echo) => {
544+ // Use the data accordingly
545+ // ...
546+ };
547+
548+ const onProgressCallback = (num) => {
549+ // Use the data accordingly
550+ // ...
551+ };
552+
553+ // Call our native addon with the paramters of a string and three callback functions
554+ nativeAddon.echo("example", onErrorCallback, onOkCallback, onProgressCallback);
555+ ```
556+
456557[ `Napi::AsyncWorker` ] : ./async_worker.md
0 commit comments