QuickJS中如何在Promise完成或拒绝时执行代码?
在QuickJS中为Promise设置then和catch回调
你已经通过JS_NewPromiseCapability创建了Promise和对应的resolve/reject函数,接下来可以通过以下步骤为这个Promise绑定then和catch回调:
1. 获取Promise原型上的then和catch方法
首先需要从Promise的原型对象上获取then和catch方法,代码如下:
// 获取Promise构造函数 JSValue promiseConstructor = JS_GetPropertyStr(ctx, JS_GetGlobalObject(ctx), "Promise"); // 获取Promise.prototype JSValue promisePrototype = JS_GetPropertyStr(ctx, promiseConstructor, "prototype"); // 获取then方法 JSValue thenMethod = JS_GetPropertyStr(ctx, promisePrototype, "then"); // 获取catch方法 JSValue catchMethod = JS_GetPropertyStr(ctx, promisePrototype, "catch"); // 释放临时对象,避免内存泄漏 JS_FreeValue(ctx, promiseConstructor); JS_FreeValue(ctx, promisePrototype);
2. 定义resolve和reject的回调函数
需要先实现QuickJS风格的回调函数,用于处理Promise的resolved和rejected状态:
// resolve回调:当Promise完成时触发 JSValue onResolved(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { // argv[0]是Promise resolve时传入的值 if (argc > 0) { const char *val = JS_ToCString(ctx, argv[0]); printf("Promise resolved with value: %s\n", val); JS_FreeCString(ctx, val); } return JS_UNDEFINED; } // reject回调:当Promise拒绝时触发 JSValue onRejected(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { // argv[0]是Promise reject时传入的原因 if (argc > 0) { const char *reason = JS_ToCString(ctx, argv[0]); printf("Promise rejected with reason: %s\n", reason); JS_FreeCString(ctx, reason); } return JS_UNDEFINED; }
3. 为Promise绑定then和catch回调
把上面定义的回调函数作为参数,调用之前获取的then和catch方法:
// 创建resolve回调的JS函数对象 JSValue resolvedFunc = JS_NewCFunction(ctx, onResolved, "onResolved", 1); // 创建reject回调的JS函数对象 JSValue rejectedFunc = JS_NewCFunction(ctx, onRejected, "onRejected", 1); // 调用then方法:promise.then(onResolved, onRejected) JSValue thenResult = JS_Call(ctx, thenMethod, promise, 2, (JSValueConst[]){resolvedFunc, rejectedFunc}); // 调用catch方法:promise.catch(onRejected) JSValue catchResult = JS_Call(ctx, catchMethod, promise, 1, (JSValueConst[]){rejectedFunc}); // 释放临时对象 JS_FreeValue(ctx, resolvedFunc); JS_FreeValue(ctx, rejectedFunc); JS_FreeValue(ctx, thenResult); JS_FreeValue(ctx, catchResult); JS_FreeValue(ctx, thenMethod); JS_FreeValue(ctx, catchMethod);
完整示例
把所有步骤整合起来,完整的可运行代码示例如下:
#include "quickjs.h" #include <stdio.h> JSValue onResolved(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { if (argc > 0) { const char *val = JS_ToCString(ctx, argv[0]); printf("Promise resolved: %s\n", val); JS_FreeCString(ctx, val); } return JS_UNDEFINED; } JSValue onRejected(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { if (argc > 0) { const char *reason = JS_ToCString(ctx, argv[0]); printf("Promise rejected: %s\n", reason); JS_FreeCString(ctx, reason); } return JS_UNDEFINED; } int main() { JSRuntime *rt = JS_NewRuntime(); JSContext *ctx = JS_NewContext(rt); // 创建PromiseCapability JSValue resolvingFuncs[2]; JSValue promise = JS_NewPromiseCapability(ctx, resolvingFuncs); JSValue resolveFunc = resolvingFuncs[0]; JSValue rejectFunc = resolvingFuncs[1]; // 获取Promise原型的then和catch方法 JSValue promiseConstructor = JS_GetPropertyStr(ctx, JS_GetGlobalObject(ctx), "Promise"); JSValue promisePrototype = JS_GetPropertyStr(ctx, promiseConstructor, "prototype"); JSValue thenMethod = JS_GetPropertyStr(ctx, promisePrototype, "then"); JSValue catchMethod = JS_GetPropertyStr(ctx, promisePrototype, "catch"); JS_FreeValue(ctx, promiseConstructor); JS_FreeValue(ctx, promisePrototype); // 创建回调函数 JSValue resolvedFunc = JS_NewCFunction(ctx, onResolved, "onResolved", 1); JSValue rejectedFunc = JS_NewCFunction(ctx, onRejected, "onRejected", 1); // 绑定then和catch JS_Call(ctx, thenMethod, promise, 2, (JSValueConst[]){resolvedFunc, rejectedFunc}); JS_Call(ctx, catchMethod, promise, 1, (JSValueConst[]){rejectedFunc}); // 测试resolve(注释掉下面一行,打开reject测试即可验证拒绝逻辑) JS_Call(ctx, resolveFunc, JS_UNDEFINED, 1, (JSValueConst[]){JS_NewString(ctx, "Success!")}); // JS_Call(ctx, rejectFunc, JS_UNDEFINED, 1, (JSValueConst[]){JS_NewString(ctx, "Error occurred!")}); // 执行事件循环,处理Promise异步回调 JS_ExecutePendingJob(rt, NULL); // 释放所有资源 JS_FreeValue(ctx, resolvedFunc); JS_FreeValue(ctx, rejectedFunc); JS_FreeValue(ctx, thenMethod); JS_FreeValue(ctx, catchMethod); JS_FreeValue(ctx, resolveFunc); JS_FreeValue(ctx, rejectFunc); JS_FreeValue(ctx, promise); JS_FreeContext(ctx); JS_FreeRuntime(rt); return 0; }
注意:QuickJS中的Promise回调是异步执行的,必须调用JS_ExecutePendingJob来处理待执行的异步任务,否则回调不会被触发。
内容的提问来源于stack exchange,提问作者Anurag Vohra
相关产品推荐
相关产品推荐

