1 /* 2 * Copyright (c) 2023 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 BASE_ASYNC_SESSION_H 17 #define BASE_ASYNC_SESSION_H 18 19 #include "napi/native_api.h" 20 #include "node_api.h" 21 22 #include "napi_session.h" 23 24 namespace OHOS::UpdateEngine { 25 constexpr int32_t RESULT_ARGC = 2; 26 27 template <typename RESULT> class BaseAsyncSession : public NapiSession { 28 public: 29 BaseAsyncSession(BaseClient *client, SessionParams &sessionParams, size_t argc, size_t callbackNumber = 1) 30 : NapiSession(client, sessionParams, argc, callbackNumber) 31 { 32 callbackRef_.resize(callbackNumber); 33 } 34 ~BaseAsyncSession()35 ~BaseAsyncSession() override 36 { 37 callbackRef_.clear(); 38 } 39 StartWork(napi_env env,size_t startIndex,const napi_value * args)40 napi_value StartWork(napi_env env, size_t startIndex, const napi_value *args) override 41 { 42 ENGINE_LOGI("BaseAsyncSession::StartWork startIndex: %{public}zu totalArgc_ %{public}zu " 43 "callbackNumber_: %{public}zu", 44 startIndex, totalArgc_, callbackNumber_); 45 PARAM_CHECK_NAPI_CALL(env, args != nullptr && totalArgc_ >= startIndex, return nullptr, "Invalid para"); 46 napi_value workName = CreateWorkerName(env); 47 PARAM_CHECK_NAPI_CALL(env, workName != nullptr, return nullptr, "Failed to worker name"); 48 49 // Check whether a callback exists. Only one callback is allowed. 50 for (size_t i = 0; (i < (totalArgc_ - startIndex)) && (i < callbackNumber_); i++) { 51 ENGINE_LOGI("CreateReference index:%u", static_cast<unsigned int>(i + startIndex)); 52 ClientStatus ret = NapiCommonUtils::IsTypeOf(env, args[i + startIndex], napi_function); 53 std::vector<std::pair<std::string, std::string>> paramInfos; 54 paramInfos.emplace_back("callback", "napi_function"); 55 PARAM_CHECK_NAPI_CALL(env, ret == ClientStatus::CLIENT_SUCCESS, 56 NapiCommonUtils::NapiThrowParamError(env, paramInfos); 57 return nullptr, "invalid type"); 58 ret = NapiCommonUtils::CreateReference(env, args[i + startIndex], 1, callbackRef_[i]); 59 PARAM_CHECK_NAPI_CALL(env, ret == ClientStatus::CLIENT_SUCCESS, return nullptr, 60 "Failed to create reference"); 61 } 62 63 napi_status status = napi_ok; 64 // Create an asynchronous call. 65 status = napi_create_async_work(env, nullptr, workName, NapiSession::ExecuteWork, NapiSession::CompleteWork, 66 this, &(worker_)); 67 68 PARAM_CHECK_NAPI_CALL(env, status == napi_ok, return nullptr, "Failed to create worker"); 69 70 // Put the thread in the task execution queue. 71 status = napi_queue_async_work_with_qos(env, worker_, napi_qos_default); 72 PARAM_CHECK_NAPI_CALL(env, status == napi_ok, return nullptr, "Failed to queue worker"); 73 napi_value result; 74 napi_create_int32(env, 0, &result); 75 return result; 76 } 77 NotifyJS(napi_env env,napi_value thisVar,const RESULT & result)78 void NotifyJS(napi_env env, napi_value thisVar, const RESULT &result) 79 { 80 ENGINE_LOGI("BaseAsyncSession::NotifyJS callbackNumber_: %{public}d", static_cast<int32_t>(callbackNumber_)); 81 napi_value callback; 82 napi_value undefined; 83 napi_value callResult; 84 napi_get_undefined(env, &undefined); 85 napi_value retArgs[RESULT_ARGC] = { 0 }; 86 87 BusinessError businessError; 88 GetBusinessError(businessError, result); 89 uint32_t ret; 90 if (businessError.errorNum != CallResult::SUCCESS) { 91 ENGINE_LOGI("BaseAsyncSession::NotifyJS error exist"); 92 ret = static_cast<uint32_t>(NapiCommonUtils::BuildBusinessError(env, retArgs[0], businessError)); 93 } else { 94 ret = static_cast<uint32_t>(result.buildJSObject(env, retArgs[1], result)); 95 } 96 PARAM_CHECK_NAPI_CALL(env, ret == napi_ok, return, "Failed to build json"); 97 98 napi_status retStatus = napi_get_reference_value(env, callbackRef_[0], &callback); 99 PARAM_CHECK_NAPI_CALL(env, retStatus == napi_ok, return, "Failed to get reference"); 100 const int callBackNumber = 2; 101 retStatus = napi_call_function(env, undefined, callback, callBackNumber, retArgs, &callResult); 102 PARAM_CHECK_NAPI_CALL(env, retStatus == napi_ok, return, "Failed to call function"); 103 // Release resources. 104 for (size_t i = 0; i < callbackNumber_; i++) { 105 napi_delete_reference(env, callbackRef_[i]); 106 callbackRef_[i] = nullptr; 107 } 108 napi_delete_async_work(env, worker_); 109 worker_ = nullptr; 110 } 111 CompleteWork(napi_env env,napi_status status)112 virtual void CompleteWork(napi_env env, napi_status status) override{}; 113 114 protected: 115 napi_async_work worker_ = nullptr; 116 std::vector<napi_ref> callbackRef_ = { 0 }; 117 }; 118 } // namespace OHOS::UpdateEngine 119 #endif // BASE_ASYNC_SESSION_H