Skip to content

Commit a56f612

Browse files
committed
Add overload of Catch that returns an IPromise or IPromise<PromisedT> to allow asynchronous continuation
These versions of Catch allow for recovery of a chain of promises by handling an error from an earlier state, then getting back into the "normal" flow of processing. Rework of PR Real-Serious-Games#77.
1 parent 824b714 commit a56f612

File tree

3 files changed

+126
-1
lines changed

3 files changed

+126
-1
lines changed

Tests/PromiseTests.cs

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ public void error_handler_is_not_invoked_for_resolved_promised()
202202
{
203203
var promise = new Promise<int>();
204204

205-
promise.Catch(e => throw new Exception("This shouldn't happen"));
205+
promise.Catch(onRejected: e => throw new Exception("This shouldn't happen"));
206206

207207
promise.Resolve(5);
208208
}
@@ -1472,5 +1472,65 @@ public void rejected_reject_callback_is_caught_by_chained_catch()
14721472

14731473
Assert.Equal(expectedException, actualException);
14741474
}
1475+
1476+
[Fact]
1477+
public void rejected_catch_returning_resolved_promise_state_is_adopted()
1478+
{
1479+
var promise = new Promise<int>();
1480+
int expectedValue = 1;
1481+
int actualValue = 0;
1482+
1483+
promise.Catch(err => Promise<int>.Resolved(expectedValue))
1484+
.Then(result => { actualValue = result; });
1485+
1486+
promise.Reject(new Exception());
1487+
1488+
Assert.Equal(expectedValue, actualValue);
1489+
}
1490+
1491+
[Fact]
1492+
public void rejected_catch_returning_rejected_promise_state_is_adopted()
1493+
{
1494+
var promise = new Promise<int>();
1495+
int expectedValue = 1;
1496+
int actualValue = 0;
1497+
1498+
promise.Catch(err => Promise<int>.Rejected(new Exception()))
1499+
.Catch(err => actualValue = expectedValue);
1500+
1501+
promise.Reject(new Exception());
1502+
1503+
Assert.Equal(expectedValue, actualValue);
1504+
}
1505+
1506+
[Fact]
1507+
public void rejected_catch_returning_resolved_promise_state_is_adopted_nongeneric()
1508+
{
1509+
var promise = new Promise();
1510+
int expectedValue = 1;
1511+
int actualValue = 0;
1512+
1513+
promise.Catch(err => Promise.Resolved())
1514+
.Then(() => { actualValue = expectedValue; });
1515+
1516+
promise.Reject(new Exception());
1517+
1518+
Assert.Equal(expectedValue, actualValue);
1519+
}
1520+
1521+
[Fact]
1522+
public void rejected_catch_returning_rejected_promise_state_is_adopted_nongeneric()
1523+
{
1524+
var promise = new Promise();
1525+
int expectedValue = 1;
1526+
int actualValue = 0;
1527+
1528+
promise.Catch(err => Promise.Rejected(new Exception()))
1529+
.Catch(err => actualValue = expectedValue);
1530+
1531+
promise.Reject(new Exception());
1532+
1533+
Assert.Equal(expectedValue, actualValue);
1534+
}
14751535
}
14761536
}

src/Promise.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ public interface IPromise<PromisedT>
5151
/// </summary>
5252
IPromise<PromisedT> Catch(Func<Exception, PromisedT> onRejected);
5353

54+
/// <summary>
55+
/// Handle errors for the promise and adopt status of returned promise..
56+
/// </summary>
57+
IPromise<PromisedT> Catch(Func<Exception, IPromise<PromisedT>> rejectionHandler);
58+
5459
/// <summary>
5560
/// Add a resolved callback that chains a value promise (optionally converting to a different value type).
5661
/// </summary>
@@ -602,6 +607,35 @@ public IPromise<PromisedT> Catch(Func<Exception, PromisedT> onRejected)
602607
return resultPromise;
603608
}
604609

610+
/// <summary>
611+
/// Handle errors for the promise and adopt status of returned promise..
612+
/// </summary>
613+
public IPromise<PromisedT> Catch(Func<Exception, IPromise<PromisedT>> recoveryMethod) {
614+
var resultPromise = new Promise<PromisedT>();
615+
resultPromise.WithName(Name);
616+
617+
Action<PromisedT> resolveHandler = v => resultPromise.Resolve(v);
618+
619+
Action<Exception> rejectHandler = ex =>
620+
{
621+
try {
622+
recoveryMethod(ex)
623+
.Progress(progress => resultPromise.ReportProgress(progress))
624+
.Then(resolve => resultPromise.Resolve(resolve))
625+
.Catch(reject => resultPromise.Reject(ex));
626+
}
627+
catch (Exception cbEx)
628+
{
629+
resultPromise.Reject(cbEx);
630+
}
631+
};
632+
633+
ActionHandlers(resultPromise, resolveHandler, rejectHandler);
634+
ProgressHandlers(resultPromise, v => resultPromise.ReportProgress(v));
635+
636+
return resultPromise;
637+
}
638+
605639
/// <summary>
606640
/// Add a resolved callback that chains a value promise (optionally converting to a different value type).
607641
/// </summary>

src/Promise_NonGeneric.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ public interface IPromise
4646
/// </summary>
4747
IPromise Catch(Action<Exception> onRejected);
4848

49+
/// <summary>
50+
/// Handle errors for the promise and adopt status of returned promise..
51+
/// </summary>
52+
IPromise Catch(Func<Exception, IPromise> onRejected);
53+
4954
/// <summary>
5055
/// Add a resolved callback that chains a value promise (optionally converting to a different value type).
5156
/// </summary>
@@ -689,6 +694,32 @@ public IPromise Catch(Action<Exception> onRejected)
689694
return resultPromise;
690695
}
691696

697+
public IPromise Catch(Func<Exception, IPromise> onRejected) {
698+
var resultPromise = new Promise();
699+
resultPromise.WithName(Name);
700+
701+
Action resolveHandler = () => resultPromise.Resolve();
702+
703+
Action<Exception> rejectHandler = ex =>
704+
{
705+
try {
706+
onRejected(ex)
707+
.Progress(progress => resultPromise.ReportProgress(progress))
708+
.Then(() => resultPromise.Resolve())
709+
.Catch(reject => resultPromise.Reject(ex));
710+
}
711+
catch (Exception cbEx)
712+
{
713+
resultPromise.Reject(cbEx);
714+
}
715+
};
716+
717+
ActionHandlers(resultPromise, resolveHandler, rejectHandler);
718+
ProgressHandlers(resultPromise, v => resultPromise.ReportProgress(v));
719+
720+
return resultPromise;
721+
}
722+
692723
/// <summary>
693724
/// Add a resolved callback that chains a value promise (optionally converting to a different value type).
694725
/// </summary>

0 commit comments

Comments
 (0)