Emscripten_fetch POST请求返回值始终为0的问题排查及可用EM_JS版本实现示例需求
问题分析与解决方案
1. emscripten_fetch是否支持携带请求头的POST请求?
当然支持,emscripten_fetch完全兼容带自定义请求头的POST请求。你遇到的Uncaught TypeError: XMLHttpRequest.open: Cannot convert argument 1 to ByteString错误,核心原因不是API不支持,而是requestMethod字段的内存被意外污染了——错误提示里的字符值56770远超出ASCII范围,说明原本的"POST"字符串被破坏了。
给你几个排查和修复的方向:
- 检查
attr变量的作用域:如果attr是栈上的局部变量,要确保后续代码没有溢出覆盖这块内存(比如其他局部变量越界、指针操作错误等)。 - 替换
strcpy为更安全的strncpy,避免字符串拷贝越界:strncpy(attr.requestMethod, "POST", EMSCRIPTEN_FETCH_REQUEST_METHOD_SIZE - 1); attr.requestMethod[EMSCRIPTEN_FETCH_REQUEST_METHOD_SIZE - 1] = '\0'; // 手动确保字符串结尾 - 验证
request变量的合法性:确认request.c_str()返回的是有效、以NULL结尾的字符串,没有包含非法字符。
另外,你的等待循环可以简化,直接用INFINITY参数让emscripten_fetch_wait一直等待请求完成,不用手动循环判断超时:
EMSCRIPTEN_RESULT ret = emscripten_fetch_wait(fetch, INFINITY); if (ret != EMSCRIPTEN_SUCCESS) { qDebug("Fetch operation failed with error code: %d", ret); emscripten_fetch_close(fetch); return; // 提前处理错误 }
2. EM_JS版本POST请求实现示例
下面给你两个实用的EM_JS实现:一个是推荐的异步回调版本(避免阻塞主线程),另一个是同步版本(匹配你之前的waitable使用习惯)。
异步回调版本(推荐)
这个版本用JavaScript的fetch API发送请求,通过回调函数把结果传回C++,不用你手动处理Promise:
#include <emscripten.h> #include <string> // 定义回调函数类型:接收响应数据和状态码 typedef void (*FetchCallback)(const char* responseData, int statusCode); // 声明EM_JS函数 extern "C" { EM_JS(void, js_post_request, (const char* url, const char* jsonData, FetchCallback callback), { // 把C字符串转成JS字符串 const urlStr = UTF8ToString(url); const dataStr = UTF8ToString(jsonData); fetch(urlStr, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: dataStr, }) .then(response => Promise.all([response.status, response.text()])) .then(([status, data]) => { // 把结果传给C++回调 callback(data, status); }) .catch(error => { // 请求失败时传递错误信息 callback(error.toString(), 0); }); }); } // 回调函数实现 void handleFetchResponse(const char* data, int status) { if (status == 200) { qDebug("Request succeeded! Response: %s", data); // 在这里处理返回的JSON数据 } else { qDebug("Request failed! Status: %d, Error: %s", status, data); } } // 发起请求的示例函数 void sendPostRequest(const std::string& url, const std::string& jsonData) { js_post_request(url.c_str(), jsonData.c_str(), handleFetchResponse); }
同步版本(仅必要时使用)
如果需要和你之前的同步等待逻辑一致,可以用XMLHttpRequest的同步模式,但注意这个会阻塞浏览器主线程,可能导致页面卡顿:
#include <emscripten.h> #include <string> extern "C" { EM_JS(const char*, js_post_request_sync, (const char* url, const char* jsonData, int* outStatus), { const urlStr = UTF8ToString(url); const dataStr = UTF8ToString(jsonData); const xhr = new XMLHttpRequest(); // 第三个参数设为false表示同步请求 xhr.open('POST', urlStr, false); xhr.setRequestHeader('Content-Type', 'application/json'); try { xhr.send(dataStr); *outStatus = xhr.status; // 分配内存存储响应内容,C++侧需要手动释放 return allocateUTF8(xhr.responseText); } catch (error) { *outStatus = 0; return allocateUTF8(error.toString()); } }); } // 同步请求示例函数 std::string sendSyncPost(const std::string& url, const std::string& jsonData) { int status = 0; const char* response = js_post_request_sync(url.c_str(), jsonData.c_str(), &status); std::string result(response); // 释放EM_JS分配的内存,避免泄漏 emscripten_free(const_cast<char*>(response)); if (status == 200) { qDebug("Sync request succeeded!"); } else { qDebug("Sync request failed, status code: %d", status); } return result; }
内容的提问来源于stack exchange,提问作者Gerald
相关产品推荐
相关产品推荐

