1# AsyncWorker 2 3`Napi::AsyncWorker` is an abstract class that you can subclass to remove many of 4the tedious tasks of moving data between the event loop and worker threads. This 5class internally handles all the details of creating and executing an asynchronous 6operation. 7 8Once created, execution is requested by calling `Napi::AsyncWorker::Queue`. When 9a thread is available for execution the `Napi::AsyncWorker::Execute` method will 10be invoked. Once `Napi::AsyncWorker::Execute` completes either 11`Napi::AsyncWorker::OnOK` or `Napi::AsyncWorker::OnError` will be invoked. Once 12the `Napi::AsyncWorker::OnOK` or `Napi::AsyncWorker::OnError` methods are 13complete the `Napi::AsyncWorker` instance is destructed. 14 15For the most basic use, only the `Napi::AsyncWorker::Execute` method must be 16implemented in a subclass. 17 18## Methods 19 20### Env 21 22Requests the environment in which the async worker has been initially created. 23 24```cpp 25Napi::Env Napi::AsyncWorker::Env() const; 26``` 27 28Returns the environment in which the async worker has been created. 29 30### Queue 31 32Requests that the work be queued for execution. 33 34```cpp 35void Napi::AsyncWorker::Queue(); 36``` 37 38### Cancel 39 40Cancels queued work if it has not yet been started. If it has already started 41executing, it cannot be cancelled. If cancelled successfully neither 42`OnOK` nor `OnError` will be called. 43 44```cpp 45void Napi::AsyncWorker::Cancel(); 46``` 47 48### Receiver 49 50```cpp 51Napi::ObjectReference& Napi::AsyncWorker::Receiver(); 52``` 53 54Returns the persistent object reference of the receiver object set when the async 55worker was created. 56 57### Callback 58 59```cpp 60Napi::FunctionReference& Napi::AsyncWorker::Callback(); 61``` 62 63Returns the persistent function reference of the callback set when the async 64worker was created. The returned function reference will receive the results of 65the computation that happened in the `Napi::AsyncWorker::Execute` method, unless 66the default implementation of `Napi::AsyncWorker::OnOK` or 67`Napi::AsyncWorker::OnError` is overridden. 68 69### SuppressDestruct 70 71```cpp 72void Napi::AsyncWorker::SuppressDestruct(); 73``` 74 75Prevents the destruction of the `Napi::AsyncWorker` instance upon completion of 76the `Napi::AsyncWorker::OnOK` callback. 77 78### SetError 79 80Sets the error message for the error that happened during the execution. Setting 81an error message will cause the `Napi::AsyncWorker::OnError` method to be 82invoked instead of `Napi::AsyncWorker::OnOK` once the 83`Napi::AsyncWorker::Execute` method completes. 84 85```cpp 86void Napi::AsyncWorker::SetError(const std::string& error); 87``` 88 89- `[in] error`: The reference to the string that represent the message of the error. 90 91### Execute 92 93This method is used to execute some tasks outside of the **event loop** on a libuv 94worker thread. Subclasses must implement this method and the method is run on 95a thread other than that running the main event loop. As the method is not 96running on the main event loop, it must avoid calling any methods from node-addon-api 97or running any code that might invoke JavaScript. Instead, once this method is 98complete any interaction through node-addon-api with JavaScript should be implemented 99in the `Napi::AsyncWorker::OnOK` method and `Napi::AsyncWorker::OnError` which run 100on the main thread and are invoked when the `Napi::AsyncWorker::Execute` method completes. 101 102```cpp 103virtual void Napi::AsyncWorker::Execute() = 0; 104``` 105 106### OnOK 107 108This method is invoked when the computation in the `Execute` method ends. 109The default implementation runs the `Callback` optionally provided when the 110`AsyncWorker` class was created. The `Callback` will by default receive no 111arguments. The arguments to the `Callback` can be provided by overriding the 112`GetResult()` method. 113 114```cpp 115virtual void Napi::AsyncWorker::OnOK(); 116``` 117### GetResult 118 119This method returns the arguments passed to the `Callback` invoked by the default 120`OnOK()` implementation. The default implementation returns an empty vector, 121providing no arguments to the `Callback`. 122 123```cpp 124virtual std::vector<napi_value> Napi::AsyncWorker::GetResult(Napi::Env env); 125``` 126 127### OnError 128 129This method is invoked after `Napi::AsyncWorker::Execute` completes if an error 130occurs while `Napi::AsyncWorker::Execute` is running and C++ exceptions are 131enabled or if an error was set through a call to `Napi::AsyncWorker::SetError`. 132The default implementation calls the `Callback` provided when the `Napi::AsyncWorker` 133class was created, passing in the error as the first parameter. 134 135```cpp 136virtual void Napi::AsyncWorker::OnError(const Napi::Error& e); 137``` 138 139### OnWorkComplete 140 141This method is invoked after the work has completed on JavaScript thread. 142The default implementation of this method checks the status of the work and 143tries to dispatch the result to `Napi::AsyncWorker::OnOk` or `Napi::AsyncWorker::Error` 144if the work has committed an error. If the work was cancelled, neither 145`Napi::AsyncWorker::OnOk` nor `Napi::AsyncWorker::Error` will be invoked. 146After the result is dispatched, the default implementation will call into 147`Napi::AsyncWorker::Destroy` if `SuppressDestruct()` was not called. 148 149```cpp 150virtual void OnWorkComplete(Napi::Env env, napi_status status); 151``` 152 153### OnExecute 154 155This method is invoked immediately on the work thread when scheduled. 156The default implementation of this method just calls the `Napi::AsyncWorker::Execute` 157and handles exceptions if cpp exceptions were enabled. 158 159The `OnExecute` method receives an `napi_env` argument. However, the `napi_env` 160must NOT be used within this method, as it does not run on the JavaScript 161thread and must not run any method that would cause JavaScript to run. In 162practice, this means that almost any use of `napi_env` will be incorrect. 163 164```cpp 165virtual void OnExecute(Napi::Env env); 166``` 167 168### Destroy 169 170This method is invoked when the instance must be deallocated. If 171`SuppressDestruct()` was not called then this method will be called after either 172`OnError()` or `OnOK()` complete. The default implementation of this method 173causes the instance to delete itself using the `delete` operator. The method is 174provided so as to ensure that instances allocated by means other than the `new` 175operator can be deallocated upon work completion. 176 177```cpp 178virtual void Napi::AsyncWorker::Destroy(); 179``` 180 181### Constructor 182 183Creates a new `Napi::AsyncWorker`. 184 185```cpp 186explicit Napi::AsyncWorker(const Napi::Function& callback); 187``` 188 189- `[in] callback`: The function which will be called when an asynchronous 190operations ends. The given function is called from the main event loop thread. 191 192Returns a `Napi::AsyncWorker` instance which can later be queued for execution by calling 193`Queue`. 194 195### Constructor 196 197Creates a new `Napi::AsyncWorker`. 198 199```cpp 200explicit Napi::AsyncWorker(const Napi::Function& callback, const char* resource_name); 201``` 202 203- `[in] callback`: The function which will be called when an asynchronous 204operations ends. The given function is called from the main event loop thread. 205- `[in] resource_name`: Null-terminated string that represents the 206identifier for the kind of resource that is being provided for diagnostic 207information exposed by the async_hooks API. 208 209Returns a `Napi::AsyncWorker` instance which can later be queued for execution by 210calling `Napi::AsyncWork::Queue`. 211 212### Constructor 213 214Creates a new `Napi::AsyncWorker`. 215 216```cpp 217explicit Napi::AsyncWorker(const Napi::Function& callback, const char* resource_name, const Napi::Object& resource); 218``` 219 220- `[in] callback`: The function which will be called when an asynchronous 221operations ends. The given function is called from the main event loop thread. 222- `[in] resource_name`: Null-terminated string that represents the 223identifier for the kind of resource that is being provided for diagnostic 224information exposed by the async_hooks API. 225- `[in] resource`: Object associated with the asynchronous operation that 226will be passed to possible async_hooks. 227 228Returns a `Napi::AsyncWorker` instance which can later be queued for execution by 229calling `Napi::AsyncWork::Queue`. 230 231### Constructor 232 233Creates a new `Napi::AsyncWorker`. 234 235```cpp 236explicit Napi::AsyncWorker(const Napi::Object& receiver, const Napi::Function& callback); 237``` 238 239- `[in] receiver`: The `this` object passed to the called function. 240- `[in] callback`: The function which will be called when an asynchronous 241operations ends. The given function is called from the main event loop thread. 242 243Returns a `Napi::AsyncWorker` instance which can later be queued for execution by 244calling `Napi::AsyncWork::Queue`. 245 246### Constructor 247 248Creates a new `Napi::AsyncWorker`. 249 250```cpp 251explicit Napi::AsyncWorker(const Napi::Object& receiver, const Napi::Function& callback, const char* resource_name); 252``` 253 254- `[in] receiver`: The `this` object passed to the called function. 255- `[in] callback`: The function which will be called when an asynchronous 256operations ends. The given function is called from the main event loop thread. 257- `[in] resource_name`: Null-terminated string that represents the 258identifier for the kind of resource that is being provided for diagnostic 259information exposed by the async_hooks API. 260 261Returns a `Napi::AsyncWork` instance which can later be queued for execution by 262calling `Napi::AsyncWork::Queue`. 263 264### Constructor 265 266Creates a new `Napi::AsyncWorker`. 267 268```cpp 269explicit Napi::AsyncWorker(const Napi::Object& receiver, const Napi::Function& callback, const char* resource_name, const Napi::Object& resource); 270``` 271 272- `[in] receiver`: The `this` object passed to the called function. 273- `[in] callback`: The function which will be called when an asynchronous 274operations ends. The given function is called from the main event loop thread. 275- `[in] resource_name`: Null-terminated string that represents the 276identifier for the kind of resource that is being provided for diagnostic 277information exposed by the async_hooks API. 278- `[in] resource`: Object associated with the asynchronous operation that 279will be passed to possible async_hooks. 280 281Returns a `Napi::AsyncWork` instance which can later be queued for execution by 282calling `Napi::AsyncWork::Queue`. 283 284 285### Constructor 286 287Creates a new `Napi::AsyncWorker`. 288 289```cpp 290explicit Napi::AsyncWorker(Napi::Env env); 291``` 292 293- `[in] env`: The environment in which to create the `Napi::AsyncWorker`. 294 295Returns an `Napi::AsyncWorker` instance which can later be queued for execution by calling 296`Napi::AsyncWorker::Queue`. 297 298### Constructor 299 300Creates a new `Napi::AsyncWorker`. 301 302```cpp 303explicit Napi::AsyncWorker(Napi::Env env, const char* resource_name); 304``` 305 306- `[in] env`: The environment in which to create the `Napi::AsyncWorker`. 307- `[in] resource_name`: Null-terminated string that represents the 308identifier for the kind of resource that is being provided for diagnostic 309information exposed by the async_hooks API. 310 311Returns a `Napi::AsyncWorker` instance which can later be queued for execution by 312calling `Napi::AsyncWorker::Queue`. 313 314### Constructor 315 316Creates a new `Napi::AsyncWorker`. 317 318```cpp 319explicit Napi::AsyncWorker(Napi::Env env, const char* resource_name, const Napi::Object& resource); 320``` 321 322- `[in] env`: The environment in which to create the `Napi::AsyncWorker`. 323- `[in] resource_name`: Null-terminated string that represents the 324identifier for the kind of resource that is being provided for diagnostic 325information exposed by the async_hooks API. 326- `[in] resource`: Object associated with the asynchronous operation that 327will be passed to possible async_hooks. 328 329Returns a `Napi::AsyncWorker` instance which can later be queued for execution by 330calling `Napi::AsyncWorker::Queue`. 331 332### Destructor 333 334Deletes the created work object that is used to execute logic asynchronously. 335 336```cpp 337virtual Napi::AsyncWorker::~AsyncWorker(); 338``` 339 340## Operator 341 342```cpp 343Napi::AsyncWorker::operator napi_async_work() const; 344``` 345 346Returns the Node-API `napi_async_work` wrapped by the `Napi::AsyncWorker` object. This 347can be used to mix usage of the C Node-API and node-addon-api. 348 349## Example 350 351The first step to use the `Napi::AsyncWorker` class is to create a new class that 352inherits from it and implement the `Napi::AsyncWorker::Execute` abstract method. 353Typically input to your worker will be saved within class' fields generally 354passed in through its constructor. 355 356When the `Napi::AsyncWorker::Execute` method completes without errors the 357`Napi::AsyncWorker::OnOK` function callback will be invoked. In this function the 358results of the computation will be reassembled and returned back to the initial 359JavaScript context. 360 361`Napi::AsyncWorker` ensures that all the code in the `Napi::AsyncWorker::Execute` 362function runs in the background out of the **event loop** thread and at the end 363the `Napi::AsyncWorker::OnOK` or `Napi::AsyncWorker::OnError` function will be 364called and are executed as part of the event loop. 365 366The code below shows a basic example of `Napi::AsyncWorker` the implementation: 367 368```cpp 369#include<napi.h> 370 371#include <chrono> 372#include <thread> 373 374using namespace Napi; 375 376class EchoWorker : public AsyncWorker { 377 public: 378 EchoWorker(Function& callback, std::string& echo) 379 : AsyncWorker(callback), echo(echo) {} 380 381 ~EchoWorker() {} 382 // This code will be executed on the worker thread 383 void Execute() override { 384 // Need to simulate cpu heavy task 385 std::this_thread::sleep_for(std::chrono::seconds(1)); 386 } 387 388 void OnOK() override { 389 HandleScope scope(Env()); 390 Callback().Call({Env().Null(), String::New(Env(), echo)}); 391 } 392 393 private: 394 std::string echo; 395}; 396``` 397 398The `EchoWorker`'s constructor calls the base class' constructor to pass in the 399callback that the `Napi::AsyncWorker` base class will store persistently. When 400the work on the `Napi::AsyncWorker::Execute` method is done the 401`Napi::AsyncWorker::OnOk` method is called and the results return back to 402JavaScript invoking the stored callback with its associated environment. 403 404The following code shows an example of how to create and use an `Napi::AsyncWorker`. 405 406```cpp 407#include<napi.h> 408 409// Include EchoWorker class 410// .. 411 412using namespace Napi; 413 414Value Echo(const CallbackInfo& info) { 415 // You need to validate the arguments here. 416 Function cb = info[1].As<Function>(); 417 std::string in = info[0].As<String>(); 418 EchoWorker* wk = new EchoWorker(cb, in); 419 wk->Queue(); 420 return info.Env().Undefined(); 421} 422``` 423 424Using the implementation of a `Napi::AsyncWorker` is straight forward. You only 425need to create a new instance and pass to its constructor the callback you want to 426execute when your asynchronous task ends and other data you need for your 427computation. Once created the only other action you have to do is to call the 428`Napi::AsyncWorker::Queue` method that will queue the created worker for execution. 429