SharpPromise 1.7.0

.NET 5.0 .NET Standard 2.0
Install-Package SharpPromise -Version 1.7.0
dotnet add package SharpPromise --version 1.7.0
<PackageReference Include="SharpPromise" Version="1.7.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add SharpPromise --version 1.7.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: SharpPromise, 1.7.0"
#r directive can be used in F# Interactive, C# scripting and .NET Interactive. Copy this into the interactive tool or source code of the script to reference the package.
// Install SharpPromise as a Cake Addin
#addin nuget:?package=SharpPromise&version=1.7.0

// Install SharpPromise as a Cake Tool
#tool nuget:?package=SharpPromise&version=1.7.0
The NuGet Team does not provide support for this client. Please contact its maintainers for support.

SharpPromise

SharpPromise is a library intended to bring JavaScript's promise patterns to C#.

CI NuGet .NET Standard GitHub

Why Promises in C#?

The Task library gets very close, but still leaves a few things to be desired. For example, in JS you can use somePromise.then(() => 42).then(result => console.log(result)) and have 42 logged to the console. In the Task library, the argument to ContinueWith is a task, and must be dealt with before you can get to the actual value. Promise's more clean interface makes it easy to get to the data you want, while still dealing with errors using the catch method.

Usage

Promise Class

There are two classes in the library, Promise and Promise<T>. Using both, you can get to as much of the Promise functionality as is possible in C#. Creating a promise is as easy as typing var promise = new Promise((resolve) => resolve());. This obviously won't do much, but the concept is simple. You do whatever you need to in the callback, and then resolve the promise when done.

The library allows you to pass in callbacks that take just the resolve action, resolve and reject (which takes no parameters), as well as a resolve with a reject that accepts an exception as the reject parameter.

The Promise<T> class has the same constructors, but also allows the resolve method to pass back a resolution paramter of type T. This is useful for things like REST calls where a return value is expected.

Then Method

When using promises, you are typically waiting until the promise is finished to do some other work. The Then method allows you to do said work after the promise has finished. The API looks like this:

IPromise Promise#Then(Action onResolve);
IPromise Promise#Then(Action onResolve, Action onReject);
IPromise Promise#Then(Action onResolve, Action<Exception> onReject);

IPromise Promise#Then<T>(Action<T> onResolve);
IPromise Promise#Then<T>(Action<T> onResolve, Action onReject);
IPromise Promise#Then<T>(Action<T> onResolve, Action<Exception> onReject);

IPromise<T> Promise#Then<T>(Func<T> onResolve);
IPromise<T> Promise#Then<T>(Func<T> onResolve, Action onReject);
IPromoise<T> Promise#Then<T>(Func<T> onResolve, Action<Exception> onReject);

IPromise Promise#Then(Func<IPromise> onResolve);
IPromise Promise#Then(Func<IPromise> onResolve, Action onReject);
IPromise Promise#Then(Func<IPromise> onResolve, Action<Exception> onReject);

IPromise<T> Promise#Then<T>(Func<IPromise<T>> onResolve);
IPromise<T> Promise#Then<T>(Func<IPromise<T>> onResolve, Action onReject);
IPromise<T> Promise#Then<T>(Func<IPromise<T>> onResolve, Action<Exception> onReject);

IPromise Promise#Then(Func<Task> onResolve);
IPromise Promise#Then(Func<Task> onResolve, Action onReject);
IPromise Promise#Then(Func<Task> onResolve, Action<Exception> onReject);

IPromise<T> Promise#Then<T>(Func<Task<T>> onResolve);
IPromise<T> Promise#Then<T>(Func<Task<T>> onResolve, Action onReject);
IPromise<T> Promise#Then<T>(Func<Task<T>> onResolve, Action<Exception> onReject);

IPromise<TResult> Promise#Then<TResult>(Func<T, TResult> onFulfilled);
IPromise<TResult> Promise#Then<TResult>(Func<T, TResult> onFulfilled, Action onRejected);
IPromise<TResult> Promise#Then<TResult>(Func<T, TResult> onFulfilled, Action<Exception> onRejected);

IPromise Promise#Then<T>(Func<T, IPromise> onResolve);
IPromise Promise#Then<T>(Func<T, IPromise> onResolve, Action onRejected);
IPromise Promise#Then<T>(Func<T, IPromise> onResolve, Action<Exception> onRejected);

IPromise Promise#Then(Func<T, Task> onResolve);
IPromise Promise#Then(Func<T, Task> onResolve, Action onRejected);
IPromise Promise#Then(Func<T, Task> onResolve, Action<Exception> onRejected);

IPromise<TResult> Promise#Then<TResult>(Func<T, IPromise<TResult>> onFulfilled);
IPromise<TResult> Promise#Then<TResult>(Func<T, IPromise<TResult>> onFulfilled, Action onRejected);
IPromise<TResult> Promise#Then<TResult>(Func<T, IPromise<TResult>> onFulfilled, Action<Exception> onRejected);

IPromise<TResult> Promise#Then<TResult>(Func<T, Task<TResult>> onResolve);
IPromise<TResult> Promise#Then<TResult>(Func<T, Task<TResult>> onResolve, Action onRejected);
IPromise<TResult> Promise#Then<TResult>(Func<T, Task<TResult>> onResolve, Action<Exception> onRejected);

This allows for all combinations of the Then functionality available to JS. When using Then, you can supply methods that don't care about the results of previous calls and don't return anything, all the way down to methods that take in the previous result and return a new result.

Catch Method

If at any point in the chain a promise fails, the remaining Then calls will be skipped and not invoked. To handle the error, use Catch to take the error and deal with what has happened. Any exception in the Then chains will be given to the Catch method.

Finally Method

The finally method will allow you to wait until the promise has been either resolved or rejected, and then perform some action. This is useful for scenarios where a cleanup needs to happen regardless of success or failure.

Examples

The Then method would be used after any work has been done.

new Promise(resolve => { var result = webService.DoWork(); resolve(result); })
.Then(() => /* Do something after the web call is made */);

new Promise(resolve => { var result = webService.DoWork(); resolve(result); })
.Then(response => /* Do something with the response */)
.Catch(ex => /* Handle the error */);

new Promise(resolve => { var result = webService.DoWork(); resolve(result); })
.Then(response => JsonConvert(response.Json))
.Then(data => /* Do something with the read data */)
.Catch(ex => /* Handle the error. An error thrown in any of the Then calls will get propagated here. */)
.Finally(() => /* Do something to clean up */);

new Promise(resolve => { var result = webService.DoWork(); resolve(result); })
.Then(response => { var result = webService.DoOtherWork(response.Data); return result; })
.Then(response => /* Do something with the subsequent call's data */);

Promise.Resolve and Promise.Reject

These are helper methods on the Promise class that make it easy to quickly jump into a promise. Most of the time, you will do something like

Promise.Resolve()
.Then(() => webService.DoWork())
.Then(response => /* Deal with response */);

to avoid having to deal with the resolve/reject helper methods.

Promise.All and Promise.Any

These helper methods will wait until either all or any of the promises have been resolved. This is useful if you want to create a lot of parallel tasks/promises that you want to run simultaneously, but then wait for them all to finish; or, if you have a number of items that could all give a result, and whichever is first is the one you want to use.

var promise1 = new Promise(resolve => ...);
var promise2 = new Promise(resolve => ...);

Promise.All(promise1, promise2)
.Then(results => /* Handle results */);

Due to C#'s strong typing, either all the promises must return the same type, or you must get the results out yourself by casting them into the type you want. This is a limitation of strongly typed languages as compared to dynamic languages.

Async/Await

SharpPromise is fully compatible with the async/await pattern, and can be used exactly the same way as using Tasks. This means that the following is functionally the same:

await Task.Run(() => {
	// Perform some async action
});

await new Promise(resolve => {
	// Perform some async action
	resolve();
});
Product Versions
.NET net5.0 net5.0-windows net6.0 net6.0-android net6.0-ios net6.0-maccatalyst net6.0-macos net6.0-tvos net6.0-windows
.NET Core netcoreapp2.0 netcoreapp2.1 netcoreapp2.2 netcoreapp3.0 netcoreapp3.1
.NET Standard netstandard2.0 netstandard2.1
.NET Framework net461 net462 net463 net47 net471 net472 net48
MonoAndroid monoandroid
MonoMac monomac
MonoTouch monotouch
Tizen tizen40 tizen60
Xamarin.iOS xamarinios
Xamarin.Mac xamarinmac
Xamarin.TVOS xamarintvos
Xamarin.WatchOS xamarinwatchos
Compatible target framework(s)
Additional computed target framework(s)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.
  • .NETStandard 2.1

    • No dependencies.
  • net5.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.7.0 394 10/28/2021
1.6.1 185 1/15/2021
1.6.0 481 8/30/2019
1.5.0 433 4/12/2019
1.4.0 494 12/11/2018
1.3.3 485 12/11/2018
1.3.2 494 12/11/2018
1.3.0 511 12/6/2018
1.2.41 505 12/6/2018
1.2.40 493 12/6/2018
1.2.33 552 10/19/2018
1.2.0 571 10/19/2018
1.1.0 578 10/3/2018
1.0.23 570 10/19/2018
1.0.22 567 10/3/2018
1.0.18 564 10/3/2018
1.0.0 713 5/8/2018

Change list:
- Updated the IPromise<T> interface to expose methods that have been there, but have been hidden
- Updated the IPromise<T> interface to handle one more type