1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#ifndef NAPI_ASYNC_RUNNER_H
#define NAPI_ASYNC_RUNNER_H

#include <napi/native_api.h>
#include <functional>
#include <string>
#include <memory>

// 前置声明,避免循环引用
class SmbServer;

/**
* 1. 上下文结构体
* 纯数据容器,负责在主线程和 Worker 线程间传递数据
*/
template <typename InputParams, typename OutputResult>
struct AsyncContext {
napi_async_work work = nullptr;
napi_deferred deferred = nullptr;
SmbServer* serverInstance = nullptr; // 核心实例指针

InputParams params; // 输入数据
OutputResult result; // 输出数据

// 业务逻辑回调
std::function<void(SmbServer*, const InputParams&, OutputResult&)> executeTask;
std::function<napi_value(napi_env, const OutputResult&)> completeTask;

bool success = true;
std::string errorMsg;
};

/**
* 2. 异步执行器类
* 包含静态回调函数,处理 N-API 的生命周期
*/
template <typename InputParams, typename OutputResult>
class AsyncRunner {
public:
using ContextType = AsyncContext<InputParams, OutputResult>;
using ExecFunc = std::function<void(SmbServer*, const InputParams&, OutputResult&)>;
using CompFunc = std::function<napi_value(napi_env, const OutputResult&)>;

/**
* 对外暴露的唯一静态入口
*/
static napi_value Run(napi_env env,
const char* resourceName,
InputParams&& params,
ExecFunc exec,
CompFunc comp) {

// 1. 获取 SmbServer 实例 (核心需求)
SmbServer* server = GetServerInstance(env);
if (!server) {
napi_throw_error(env, nullptr, "Fatal: SmbServer instance not found in global data.");
return nullptr;
}

// 2. 初始化上下文
auto context = new ContextType();
context->serverInstance = server;
context->params = std::forward<InputParams>(params);
context->executeTask = exec;
context->completeTask = comp;

// 3. 创建 Promise
napi_value promise;
if (napi_create_promise(env, &context->deferred, &promise) != napi_ok) {
delete context;
return nullptr;
}

// 4. 创建并排队异步工作
napi_value resourceNameVal;
napi_create_string_utf8(env, resourceName, NAPI_AUTO_LENGTH, &resourceNameVal);

napi_status status = napi_create_async_work(
env, nullptr, resourceNameVal,
OnExecute, // 拆分出的 Worker 线程逻辑
OnComplete, // 拆分出的 Main 线程逻辑
context,
&context->work
);

if (status != napi_ok) {
delete context;
return nullptr;
}

napi_queue_async_work(env, context->work);
return promise;
}

private:
// 辅助函数:获取存储的实例指针
static SmbServer* GetServerInstance(napi_env env) {
void* data = nullptr;
napi_get_instance_data(env, &data);
return static_cast<SmbServer*>(data);
}

// --- Worker 线程回调 ---
static void OnExecute(napi_env env, void* data) {
auto ctx = static_cast<ContextType*>(data);
if (!ctx) return;

try {
if (ctx->executeTask && ctx->serverInstance) {
// 执行具体的 C++ 业务
ctx->executeTask(ctx->serverInstance, ctx->params, ctx->result);
}
} catch (const std::exception& e) {
ctx->success = false;
ctx->errorMsg = e.what();
} catch (...) {
ctx->success = false;
ctx->errorMsg = "Unknown native error";
}
}

// --- Main 线程回调 (Promise Resolve/Reject) ---
static void OnComplete(napi_env env, napi_status status, void* data) {
auto ctx = static_cast<ContextType*>(data);
if (!ctx) return;

napi_value resultVal = nullptr;

if (status == napi_ok && ctx->success) {
// 成功:转换结果并 Resolve
if (ctx->completeTask) {
resultVal = ctx->completeTask(env, ctx->result);
} else {
napi_get_undefined(env, &resultVal);
}
napi_resolve_deferred(env, ctx->deferred, resultVal);
} else {
// 失败:构造错误并 Reject
napi_value errorMsg, errorObj;
std::string msg = ctx->errorMsg.empty() ? "Async failure" : ctx->errorMsg;
napi_create_string_utf8(env, msg.c_str(), NAPI_AUTO_LENGTH, &errorMsg);
napi_create_error(env, nullptr, errorMsg, &errorObj);
napi_reject_deferred(env, ctx->deferred, errorObj);
}

// 资源清理
napi_delete_async_work(env, ctx->work);
delete ctx;
}
};

#endif // NAPI_ASYNC_RUNNER_H
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// 输入参数结构体
struct ConnectParams {
std::string ip;
int port;
};

// 输出结果结构体
struct ConnectResult {
bool isConnected;
std::string message;
};

#include "NapiAsyncHelper.h"
#include "SmbServer.h" // 假设这是你的类定义

// 对外暴露的 JS 接口: smbServer.connect(ip, port)
napi_value JS_Connect(napi_env env, napi_callback_info info) {
// 1. 解析 JS 参数
size_t argc = 2;
napi_value args[2];
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

// 填充输入参数
ConnectParams params;
// ... 省略具体的 napi_get_value_string 等参数解析代码 ...
// 假设解析完成:
// params.ip = "192.168.1.10";
// params.port = 445;

// 2. 调用模板函数
// 模板参数 <ConnectParams, ConnectResult> 会自动推导,也可以显式写出
return NapiAsyncPromise<ConnectParams, ConnectResult>(
env,
"SmbConnectWorker", // 任务名称
std::move(params), // 传入参数

// --- 异步执行逻辑 (Worker Thread) ---
// 注意:这里禁止调用任何 napi_ 接口!只能跑 C++ 纯逻辑
[](SmbServer* server, const ConnectParams& in, ConnectResult& out) {
// 这里我们直接拿到了 server 指针!
if (server) {
// 调用 SmbServer 的同步阻塞方法
int ret = server->DoConnectLogic(in.ip, in.port);

out.isConnected = (ret == 0);
out.message = out.isConnected ? "Success" : "Connection Timeout";
} else {
out.isConnected = false;
out.message = "Instance is null";
}
},

// --- 结果转换逻辑 (Main Thread) ---
// 这里可以调用 napi_ 接口将 C++ 结果转 JS
[](napi_env env, const ConnectResult& out) -> napi_value {
napi_value resultObj;
napi_create_object(env, &resultObj);

napi_value statusVal, msgVal;
napi_get_boolean(env, out.isConnected, &statusVal);
napi_create_string_utf8(env, out.message.c_str(), NAPI_AUTO_LENGTH, &msgVal);

napi_set_named_property(env, resultObj, "success", statusVal);
napi_set_named_property(env, resultObj, "message", msgVal);

return resultObj; // 这个对象会被 Resolve 回去
}
);
}