Skip to content

Commit a8ae1fa

Browse files
feat: add Then method with onRejected handler to Promise class
1 parent 4717a3d commit a8ae1fa

File tree

4 files changed

+78
-5
lines changed

4 files changed

+78
-5
lines changed

napi-inl.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2835,6 +2835,28 @@ inline MaybeOrValue<Promise> Promise::Then(napi_value onFulfilled) const {
28352835
#endif
28362836
}
28372837

2838+
inline MaybeOrValue<Promise> Promise::Then(napi_value onFulfilled, napi_value onRejected) const {
2839+
EscapableHandleScope scope(_env);
2840+
#ifdef NODE_ADDON_API_ENABLE_MAYBE
2841+
MaybeOrValue<Value> thenMethodMaybe = Get("then");
2842+
Function thenMethod = thenMethodMaybe.Unwrap().As<Function>();
2843+
#else
2844+
Function thenMethod = Get("then").As<Function>();
2845+
#endif
2846+
MaybeOrValue<Value> result = thenMethod.Call(*this, {onFulfilled, onRejected});
2847+
#ifdef NODE_ADDON_API_ENABLE_MAYBE
2848+
if (result.IsJust()) {
2849+
return Just(scope.Escape(result.Unwrap()).As<Promise>());
2850+
}
2851+
return Nothing<Promise>();
2852+
#else
2853+
if (scope.Env().IsExceptionPending()) {
2854+
return Promise();
2855+
}
2856+
return scope.Escape(result).As<Promise>();
2857+
#endif
2858+
}
2859+
28382860
////////////////////////////////////////////////////////////////////////////////
28392861
// Buffer<T> class
28402862
////////////////////////////////////////////////////////////////////////////////

napi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1578,6 +1578,7 @@ class Promise : public Object {
15781578
Promise(napi_env env, napi_value value);
15791579

15801580
MaybeOrValue<Promise> Then(napi_value onFulfilled) const;
1581+
MaybeOrValue<Promise> Then(napi_value onFulfilled, napi_value onRejected) const;
15811582
};
15821583

15831584
template <typename T>

test/promise.cc

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,40 @@ Value ThenMethodOnFulfilled(const CallbackInfo& info) {
4040
return result;
4141
}
4242

43+
Value ThenMethodOnFulfilledOnRejectedResolve(const CallbackInfo& info) {
44+
auto deferred = Promise::Deferred::New(info.Env());
45+
Function onFulfilled = info[0].As<Function>();
46+
Function onRejected = info[1].As<Function>();
47+
48+
Promise resultPromise = MaybeUnwrap(deferred.Promise().Then(onFulfilled, onRejected));
49+
50+
bool isPromise = resultPromise.IsPromise();
51+
deferred.Resolve(Number::New(info.Env(), 42));
52+
53+
Object result = Object::New(info.Env());
54+
result["isPromise"] = Boolean::New(info.Env(), isPromise);
55+
result["promise"] = resultPromise;
56+
57+
return result;
58+
}
59+
60+
Value ThenMethodOnFulfilledOnRejectedReject(const CallbackInfo& info) {
61+
auto deferred = Promise::Deferred::New(info.Env());
62+
Function onFulfilled = info[0].As<Function>();
63+
Function onRejected = info[1].As<Function>();
64+
65+
Promise resultPromise = MaybeUnwrap(deferred.Promise().Then(onFulfilled, onRejected));
66+
67+
bool isPromise = resultPromise.IsPromise();
68+
deferred.Reject(String::New(info.Env(), "Rejected"));
69+
70+
Object result = Object::New(info.Env());
71+
result["isPromise"] = Boolean::New(info.Env(), isPromise);
72+
result["promise"] = resultPromise;
73+
74+
return result;
75+
}
76+
4377
Object InitPromise(Env env) {
4478
Object exports = Object::New(env);
4579

@@ -48,7 +82,11 @@ Object InitPromise(Env env) {
4882
exports["rejectPromise"] = Function::New(env, RejectPromise);
4983
exports["promiseReturnsCorrectEnv"] =
5084
Function::New(env, PromiseReturnsCorrectEnv);
51-
exports["ThenMethodOnFulfilled"] = Function::New(env, ThenMethodOnFulfilled);
85+
exports["thenMethodOnFulfilled"] = Function::New(env, ThenMethodOnFulfilled);
86+
exports["thenMethodOnFulfilledOnRejectedResolve"] =
87+
Function::New(env, ThenMethodOnFulfilledOnRejectedResolve);
88+
exports["thenMethodOnFulfilledOnRejectedReject"] =
89+
Function::New(env, ThenMethodOnFulfilledOnRejectedReject);
5290

5391
return exports;
5492
}

test/promise.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,20 @@ async function test (binding) {
1919
assert(binding.promise.promiseReturnsCorrectEnv());
2020

2121
const onFulfilled = (value) => value * 2;
22-
const result = binding.promise.thenMethodOnFulfilled(onFulfilled);
23-
assert.strictEqual(result.isPromise, true);
24-
const finalValue = await result.promise;
25-
assert.strictEqual(finalValue, 84);
22+
const onRejected = (reason) => reason + '!';
23+
24+
const thenOnFulfilled = binding.promise.thenMethodOnFulfilled(onFulfilled);
25+
assert.strictEqual(thenOnFulfilled.isPromise, true);
26+
const onFulfilledValue = await thenOnFulfilled.promise;
27+
assert.strictEqual(onFulfilledValue, 84);
28+
29+
const thenResolve = binding.promise.thenMethodOnFulfilledOnRejectedResolve(onFulfilled, onRejected);
30+
assert.strictEqual(thenResolve.isPromise, true);
31+
const thenResolveValue = await thenResolve.promise;
32+
assert.strictEqual(thenResolveValue, 84);
33+
34+
const thenRejected = binding.promise.thenMethodOnFulfilledOnRejectedReject(onFulfilled, onRejected);
35+
assert.strictEqual(thenRejected.isPromise, true);
36+
const rejectedValue = await thenRejected.promise;
37+
assert.strictEqual(rejectedValue, 'Rejected!');
2638
}

0 commit comments

Comments
 (0)