1 /* 2 * Copyright (C) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef PROMISE_BASE_H 17 #define PROMISE_BASE_H 18 19 #include <napi_api.h> 20 21 /** 22 * @brief Provide an async state with JavaScript promise semantics. 23 * 24 * Usage example: 25 * struct Promise : public PromiseBase { 26 * using PromiseBase::PromiseBase; 27 * NapiApi::StrongRef arg; 28 * bool SetResult() override { 29 * result_ = DoSomethingWith(arg); 30 * } 31 * }; 32 * auto promise = new Promise(); 33 * promise->arg = someVariable; 34 * auto jsValue = promise->ToNapiValue(); // Extract the JS promise before settling. 35 * promise->SettleLater(); // After a settle call, do not touch the promise object. 36 * return jsValue; 37 * 38 * @note An instance must be dynamically allocated (into a raw pointer) and created in the main thread. Call one of 39 * SettleLater, SettleNow or Reject to settle the promise. After settling, the object will delete itself. 40 */ 41 class PromiseBase { 42 public: 43 /** 44 * @brief Call only with new, in the main thread that is local to the given napi_env. 45 */ 46 explicit PromiseBase(napi_env env); 47 virtual ~PromiseBase(); 48 49 /** 50 * @brief Get the JavaScript promise object. 51 */ 52 napi_value ToNapiValue() const; 53 54 /** 55 * @brief Settle the promise later, in the JS thread, and delete this object. 56 * @note Call only from the engine thread. After calling, do not use this object. 57 */ 58 void SettleLater(); 59 60 /** 61 * @brief Settle the promise immediately and delete this object. 62 * @note After calling, do not use this object. 63 */ 64 void SettleNow(); 65 66 /** 67 * @brief Settle the promise immediately without fulfilling it and delete this object. 68 * @note After calling, do not use this object. 69 */ 70 void Reject(); 71 72 protected: 73 /** 74 * @brief Set the result of the promise. 75 * @return True on success. If false, the promise will be rejected. 76 * @note SettleLater will run this in the JS thread; SettleNow in the same thread where it was called. 77 */ 78 virtual bool SetResult() = 0; 79 napi_value result_ { nullptr }; 80 napi_env env_ { nullptr }; 81 82 private: 83 void Resolve(); 84 void CreateJsPromise(); 85 void CreateSettleFunc(); 86 void ReleaseSettleFunc(); 87 void Abort(); 88 89 static inline void SettleCB(napi_env env, napi_value js_callback, void* context, void* inData); 90 static inline void FinalizeCB(napi_env env, void* finalize_data, void* finalize_hint); 91 92 napi_deferred deferred_ { nullptr }; 93 napi_value promise_ { nullptr }; 94 napi_threadsafe_function settleLaterFunc_ { nullptr }; 95 }; 96 97 #endif 98