Last active
November 24, 2015 05:40
-
-
Save ykst/75599365f2c79c9d6450 to your computer and use it in GitHub Desktop.
Deferred in C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Deferred | |
{ | |
public class BasePromise | |
{ | |
protected enum State | |
{ | |
Pending, | |
Fullfilled, | |
Rejected | |
} | |
protected delegate void OnFullfilled(); | |
protected delegate void OnRejected(System.Exception reason); | |
protected event OnFullfilled onFullfilledHandlers = null; | |
protected event OnRejected onRejectedHandlers = null; | |
protected State _state = State.Pending; | |
protected System.Exception _reason = null; | |
public bool IsResolved { get { return _state == State.Fullfilled; } } | |
protected void Defer(OnFullfilled onFullfilled, OnRejected onRejected = null) | |
{ | |
switch (_state) { | |
case State.Pending: | |
onFullfilledHandlers += onFullfilled; | |
if (onRejected != null) { | |
onRejectedHandlers += onRejected; | |
} | |
break; | |
case State.Fullfilled: | |
onFullfilled(); | |
break; | |
case State.Rejected: | |
if (onRejected != null) { | |
onRejected(_reason); | |
} | |
break; | |
} | |
} | |
protected void Defer(BasePromise promise, OnFullfilled onFullfilled, System.Action<System.Exception> onRejected = null) | |
{ | |
Defer(onFullfilled, (reason) => { | |
ForwardReject(promise, reason, onRejected); | |
}); | |
} | |
public void ForwardPromise(Promise promise) | |
{ | |
Defer(() => { | |
promise.Resolve(); | |
}, (reason) => { | |
promise.Reject(reason); | |
}); | |
} | |
protected void ForwardReject(BasePromise promise, System.Exception reason, System.Action<System.Exception> onRejected = null) | |
{ | |
if (onRejected != null) { | |
try { | |
onRejected(reason); | |
} | |
catch (System.Exception reason2) { | |
Debug.LogException(reason2); | |
reason = reason2; | |
} | |
} | |
promise.Reject(reason); | |
} | |
public void Reject(System.Exception reason) | |
{ | |
if (_state != State.Pending) { | |
throw new System.Exception("illegal promise state"); | |
} | |
_reason = reason; | |
if (onRejectedHandlers != null) { | |
onRejectedHandlers(reason); | |
} | |
onRejectedHandlers = null; | |
_state = State.Rejected; | |
} | |
protected void ResolveImpl() | |
{ | |
if (_state != State.Pending) { | |
throw new System.Exception("illegal promise state"); | |
} | |
if (onFullfilledHandlers != null) { | |
onFullfilledHandlers(); | |
} | |
onFullfilledHandlers = null; | |
_state = State.Fullfilled; | |
} | |
public BasePromise Unless(System.Action whenNotFullfilled) | |
{ | |
if (_state == State.Pending) { | |
whenNotFullfilled(); | |
} | |
return this; | |
} | |
public void Done(System.Action onFullfilled, System.Action<System.Exception> onRejected = null) | |
{ | |
Defer(() => { | |
onFullfilled(); | |
}, (reason) => { | |
if (onRejected != null) { | |
onRejected(reason); | |
} | |
}); | |
} | |
public void Finally(System.Action onDone) | |
{ | |
Defer(() => { onDone(); }, (_) => { onDone(); }); | |
} | |
} | |
public class Promise : BasePromise | |
{ | |
public void Resolve() | |
{ | |
ResolveImpl(); | |
} | |
public Promise Then(System.Action onFullfilled, System.Action<System.Exception> onRejected = null) | |
{ | |
Promise promise = new Promise(); | |
Defer(promise, () => { | |
try { | |
onFullfilled(); | |
} | |
catch (System.Exception reason) { | |
Debug.LogException(reason); | |
ForwardReject(promise, reason, onRejected); | |
return; | |
} | |
promise.Resolve(); | |
}, onRejected); | |
return promise; | |
} | |
public Promise<T> Then<T>(System.Func<T> onFullfilled, System.Action<System.Exception> onRejected = null) | |
{ | |
Promise<T> promise = new Promise<T>(); | |
Defer(promise, () => { | |
T value; | |
try { | |
value = onFullfilled(); | |
} | |
catch (System.Exception reason) { | |
Debug.LogException(reason); | |
ForwardReject(promise, reason, onRejected); | |
return; | |
} | |
promise.Resolve(value); | |
}, onRejected); | |
return promise; | |
} | |
public Promise ThenPromise(System.Func<Promise> onFullfilled, System.Action<System.Exception> onRejected = null) | |
{ | |
Promise promise = new Promise(); | |
Defer(promise, () => { | |
Promise nextPromise; | |
try { | |
nextPromise = onFullfilled(); | |
} | |
catch (System.Exception reason) { | |
Debug.LogException(reason); | |
ForwardReject(promise, reason, onRejected); | |
return; | |
} | |
nextPromise.ForwardPromise(promise); | |
}, onRejected); | |
return promise; | |
} | |
public Promise Catch(System.Action<System.Exception> onRejected) | |
{ | |
Promise promise = new Promise(); | |
Defer(promise, promise.Resolve, onRejected); | |
return promise; | |
} | |
public static Promise Always() | |
{ | |
Promise promise = new Promise(); | |
promise.Resolve(); | |
return promise; | |
} | |
} | |
public class Promise<T> : BasePromise | |
{ | |
T _value; | |
public void Resolve(T value) | |
{ | |
_value = value; | |
ResolveImpl(); | |
} | |
public Promise Then(System.Action<T> onFullfilled, System.Action<System.Exception> onRejected = null) | |
{ | |
Promise promise = new Promise(); | |
Defer(promise, () => { | |
try { | |
onFullfilled(_value); | |
} | |
catch (System.Exception reason) { | |
Debug.LogException(reason); | |
ForwardReject(promise, reason, onRejected); | |
return; | |
} | |
promise.Resolve(); | |
}, onRejected); | |
return promise; | |
} | |
public Promise<R> Then<R>(System.Func<T, R> onFullfilled, System.Action<System.Exception> onRejected = null) | |
{ | |
Promise<R> promise = new Promise<R>(); | |
Defer(promise, () => { | |
R nextValue; | |
try { | |
nextValue = onFullfilled(_value); | |
} | |
catch (System.Exception reason) { | |
Debug.LogException(reason); | |
ForwardReject(promise, reason, onRejected); | |
return; | |
} | |
promise.Resolve(nextValue); | |
}, onRejected); | |
return promise; | |
} | |
public Promise ThenPromise(System.Func<T, Promise> onFullfilled, System.Action<System.Exception> onRejected = null) | |
{ | |
Promise promise = new Promise(); | |
Defer(promise, () => { | |
Promise nextPromise; | |
try { | |
nextPromise = onFullfilled(_value); | |
} | |
catch (System.Exception reason) { | |
Debug.LogException(reason); | |
ForwardReject(promise, reason, onRejected); | |
return; | |
} | |
nextPromise.ForwardPromise(promise); | |
}, onRejected); | |
return promise; | |
} | |
public void Done(System.Action<T> onFullfilled, System.Action<System.Exception> onRejected = null) | |
{ | |
Defer(() => { | |
onFullfilled(_value); | |
}, (reason) => { | |
if (onRejected != null) { | |
onRejected(reason); | |
} | |
}); | |
} | |
public Promise<T> Catch(System.Action<System.Exception> onRejected) | |
{ | |
Promise<T> promise = new Promise<T>(); | |
Defer(promise, () => { | |
promise.Resolve(_value); | |
}, onRejected); | |
return promise; | |
} | |
public static Promise<T> Always(T value) | |
{ | |
Promise<T> promise = new Promise<T>(); | |
promise.Resolve(value); | |
return promise; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment