• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef REQUEST_ASYNC_CALL_H
16 #define REQUEST_ASYNC_CALL_H
17 
18 #include <functional>
19 #include <memory>
20 #include <string>
21 
22 #include "constant.h"
23 #include "js_common.h"
24 #include "log.h"
25 #include "napi/native_node_api.h"
26 #include "napi_utils.h"
27 
28 namespace OHOS::Request {
29 class AsyncCall final {
30 public:
31     class Context {
32     public:
33         using InputAction = std::function<napi_status(size_t, napi_value *, napi_value)>;
34         using OutputAction = std::function<napi_status(napi_value *)>;
35         using ExecAction = std::function<void()>;
36         Context() = default;
~Context()37         virtual ~Context()
38         {
39             ContextNapiHolder *holder =
40                 new ContextNapiHolder{ .env = env_, .callbackRef = callbackRef_, .self = self_, .work = work_ };
41             auto afterCallback = [holder]() {
42                 napi_handle_scope scope = nullptr;
43                 napi_open_handle_scope(holder->env, &scope);
44                 if (scope == nullptr) {
45                     delete holder;
46                     return;
47                 } else if (holder->env == nullptr || holder->work == nullptr || holder->self == nullptr) {
48                     napi_close_handle_scope(holder->env, scope);
49                     delete holder;
50                     return;
51                 }
52                 napi_delete_async_work(holder->env, holder->work);
53                 napi_delete_reference(holder->env, holder->self);
54                 if (holder->callbackRef != nullptr) {
55                     napi_delete_reference(holder->env, holder->callbackRef);
56                 }
57                 napi_close_handle_scope(holder->env, scope);
58                 delete holder;
59             };
60             int32_t ret = napi_send_event(env_, afterCallback, napi_eprio_high);
61             if (ret != napi_ok) {
62                 REQUEST_HILOGE("napi_send_event failed: %{public}d", ret);
63                 delete holder;
64             }
65         };
SetInput(InputAction action)66         inline Context &SetInput(InputAction action)
67         {
68             input_ = std::move(action);
69             return *this;
70         }
SetOutput(OutputAction action)71         inline Context &SetOutput(OutputAction action)
72         {
73             output_ = std::move(action);
74             return *this;
75         }
SetExec(ExecAction action)76         inline Context &SetExec(ExecAction action)
77         {
78             exec_ = std::move(action);
79             return *this;
80         }
CreateErr()81         inline napi_value CreateErr()
82         {
83             ExceptionError error;
84             NapiUtils::ConvertError(innerCode_, error);
85             return NapiUtils::CreateBusinessError(env_, error.code, error.errInfo, withErrCode_);
86         }
87 
88         InputAction input_ = nullptr;
89         OutputAction output_ = nullptr;
90         ExecAction exec_ = nullptr;
91 
92         napi_env env_;
93         napi_ref callbackRef_ = nullptr;
94         napi_ref self_ = nullptr;
95         napi_deferred defer_ = nullptr;
96         napi_async_work work_ = nullptr;
97 
98         int32_t innerCode_;
99         bool withErrCode_;
100         Version version_;
101     };
102 
103     AsyncCall(napi_env env, napi_callback_info info, const std::shared_ptr<Context> &context);
104     ~AsyncCall();
105     napi_value Call(const std::shared_ptr<Context> &context, const std::string &resourceName = "AsyncCall");
106 
SetQosLevel(napi_qos_t napiQosLevel)107     inline void SetQosLevel(napi_qos_t napiQosLevel)
108     {
109         napiQosLevel_ = napiQosLevel;
110     }
111 
112 private:
113     enum { ARG_ERROR, ARG_DATA, ARG_BUTT };
114 
115     struct WorkData {
116         std::shared_ptr<Context> ctx = nullptr;
~WorkDataWorkData117         ~WorkData()
118         {
119             ctx = nullptr;
120         }
121     };
122 
123     struct ContextNapiHolder {
124         napi_env env;
125         napi_ref callbackRef;
126         napi_ref self;
127         napi_async_work work;
128     };
129     static void OnExecute(napi_env env, void *data);
130     static void OnComplete(napi_env env, napi_status status, void *data);
131     napi_qos_t napiQosLevel_ = napi_qos_default;
132 };
133 } // namespace OHOS::Request
134 #endif // ASYNC_CALL_H
135