Giter Club home page Giter Club logo

c-sharp-promise's People

Contributors

adamsingle avatar alonsohki avatar ashleydavis avatar biro456 avatar borningstar avatar brknrobot avatar edycer avatar jdnichollsc avatar kalvinpearce avatar konh avatar mointom avatar renanse avatar rorydungan avatar sindrijo avatar thejenix avatar vanillajonathan avatar xenmax avatar zsoi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

c-sharp-promise's Issues

Promise method is not thread safe.

hi, I'm use the tools for my Unity project, but encounter some exception seems about thread safe problem.
A simple stage can reproduction it:
Simulating 10000 times Promise.Then<T> method inner ThreadPool by for statement will throw some exception at Promise<T>.InvokeResolveHandlers's resolveCallbacks [i] line (about at 326 lines), I have suffered array out of index and object is null.
I think add some lock for resolveCallbacks, resolveRejectables and rejectHandlers is a good idea.

Exceptions in immediately called function?

Hi,

Suppose we have the following:

private IPromise DownloadFile()
{
    return DoAsyncOp1()
        .Then(x => DoAsynOp2())
        .Catch(e => Debugger.Log("Whoopsie!"));
}

private IPromise DoAsyncOp1()
{
    // If we throw an exception here, it wont be caught in the handler above
}

private IPromise DoAsynOp2()
{
    // If we throw an exception here, it WILL be caught in the handler above
}

Is the how would you engineer a safe solution to this? Would you do:

private IPromise DownloadFile()
{โ€‹
    return Promise.Resolve()
        .Then(() => DoAsyncOp1())
        .Then(x => DoAsynOp2())
        .Catch(e => Debugger.Log("Whoopsie!"));
}
private IPromise DoAsyncOp1()
{
    // If we throw an exception here, it will now be caught
}
private IPromise DoAsynOp2()
{
    // If we throw an exception here, it will also be caught
}

Or how would you structure your code? To be safe should you ALWAYS start every promise with Promise.Resolve() ?

Cheers,
Mike

Is .Done() equal to JS .finally()?

I've read through the source and don't think .Done(resolved, rejected) is equal to JavaScript's .finally(), is that correct? I know that .finally() is not officially in the spec, but almost all non-native Promise implementations offer the functionality and I think it'd be quite useful for game-development purposes as well.

In that case, would you mind adding a .Finally(Action) method? I'll see if I can create a pull request myself if it's not already on your agenda.

Best Regards
Philipp

Exception handling not consistent with A+

Consider the following JavaScript code:

const Promise = require('bluebird'); // Using native promises does not change the behavior

Promise.resolve()
  .then(() => {
    console.log('then1');
    throw new Error('Foo');
  })
  .catch(() => {
    console.log('catch');
  })
  .then(() => {
    console.log('then2');
  })

The output:

then1
catch
then2

Now, using RSG promises:

void Start () {
	 Promise.Resolved()
            .Then(() => {
                Debug.Log("Then1");
                throw new NotImplementedException("NO!");
            })
            .Catch((e) => {
		Debug.Log("Catch");
	    });
	    .Then(() => {
		Debug.Log("Then2");
            });
}

The output:

then1
catch

(Using v1.2.2)

Corresponding A+ spec rule: https://promisesaplus.com/#point-41

If either onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x).

Benefit of calling both Catch() and Done()?

This isn't so much an issue as a general question (sorry if there's a better place to put this, I wasn't sure). I notice that in examples 3, 4, and 5, you do the following pattern:

SomePromise
  .Then(() => {})
  .Catch(e => {})
  .Done();

Is there a benefit to calling both Catch and Done in these cases? I can see recovering from an exception in Catch and calling another Then, but the Done seems redundant.

Am I missing something?

To Coroutine

Hi,

Is there a way to convert a Promise to a Coroutine (to keep consistency with for legacy code)?

Cheers,
Mike

Incorrect overloads of .Then and .Catch

There are currently 3 overloads of Promise<T>.Then that don't make sense and 1 of Promise.Then:

interface IPromise<PromisedT>
{
    // These should be changed to return a non-generic promise because the callbacks don't 
    // return a value
    IPromise<PromisedT> Then(Action<PromisedT> onResolved, Action<Exception> onRejected);
    IPromise<PromisedT> Then(Action<PromisedT> onResolved);

    // This should be changed to return IPromise<ConvertedT> to be more flexible.
    // Changing to ConvertedT would retain backwards compatibility because ConvertedT can be
    // the same as PromisedT
    // IPromise<PromisedT> Catch(Func<Exception, PromisedT> onRejected);
    // EDIT: this actually doesn't work - see below
}

interface IPromise
{
    // Now that onRejected handlers can return values, this no longer makes sense. The second
    // argument should be type 'Func<Exception, ConvertedT>' or 'Func<Exception, IPromise<ConvertedT>>'
    IPromise<ConvertedT> Then<ConvertedT>(Func<IPromise<ConvertedT>> onResolved, Action<Exception> onRejected);
}

These should be modified to fit the rest of the library or just removed.

In addition, there are many helpful overloads of .Then and .Catch that we could add to support use in a more similar way to JS Promises:

// Generic promise
IPromise<ConvertedT> Then(Func<PromisedT, ConvertedT> onResolved, Func<Exception, ConvertedT> onRejected);
IPromise<ConvertedT> Then(Func<PromisedT, IPromise<ConvertedT>> onResolved, Func<Exception, ConvertedT> onRejected);
IPromise<ConvertedT> Then(Func<PromisedT, ConvertedT> onResolved, Func<Exception, IPromise<ConvertedT>> onRejected);
IPromise<PromisedT> Catch(Func<Exception, IPromise<PromisedT>> onRejected);
IPromise Then(Action<PromisedT> onResolved);
IPromise Then(Action<PromisedT> onResolved, Action<Exception> onRejected);
IPromise Then(Action<PromisedT> onResolved, Func<Exception, IPromise> onRejected);
IPromise Then(Func<PromisedT, IPromise> onResolved, Func<Exception, IPromise> onRejected);
IPromise Catch(Func<Exception, IPromise> onRejected);

// Non-generic promise
IPromise<ConvertedT> Then(Func<ConvertedT> onResolved);
IPromise<ConvertedT> Then(Func<ConvertedT> onResolved, Func<Exception, ConvertedT> onRejected);
IPromise<ConvertedT> Then(Func<IPromise<ConvertedT>> onResolved, Func<Exception, ConvertedT> onRejected);
IPromise<ConvertedT> Then(Func<ConvertedT> onResolved, Func<Exception, IPromise<ConvertedT>> onRejected);
IPromise<ConvertedT> Then(Func<IPromise<ConvertedT>> onResolved, Func<Exception, IPromise<ConvertedT>> onRejected);
IPromise Then(Action onResolved, Func<Exception, IPromise> onRejected);
IPromise Then(Func<IPromise> onResolved, Func<Exception, IPromise> onRejected);
IPromise Catch(Func<Exception, IPromise> onRejected);

Most of these could be implemented quite easily by simply making them call through to the existing methods.

Is there a "Always" callback?

Hello!

Quick question.
Is there a callback that is going to be called wether the "request" succeeded or not?

Let's say I'm starting a promise, and either it succeed or not, I want to call a specific method. And I don't want to have to call the method in "Then" and also in "Catch". Is there a way to do that?

Thanks!

How to keep the "same" promise when chained?

Hey guys :)

I just stumbled upon a small issue.
I'm using the code below:

public static IPromise<ProcessResult> ChmodAndExecute(string filePath)
{
	Promise<ProcessResult> promise = new Promise<ProcessResult>();

	ExecuteProcess("chmod", "+x \"" + filePath + "\"")
	.Then(processResult => 
	{
		return ExecuteProcess(filePath);
	})
	.Catch(exception =>
	{
		promise.Reject(exception);
	});

	return promise;
}

And calling it using:

ProcessUtils.ChmodAndExecute(serverPath)
.Then((ProcessUtils.ProcessResult processResult) => 
{
	// Do something here
})
.Catch(exception =>
{
	// ...
});

The thing is that, I never enter inside the // Do something here.
It's because I'm using return ExecuteProcess(filePathWithArguments); in the ChmodAndExecute method, and inside this ExecuteProcess method, I create ANOTHER promise.

One way I fixed it is by passing the already existing promise to my ExecuteProcess method, doing return ExecuteProcess(promise, filePathWithArguments); like below

public static IPromise<ProcessResult> ChmodAndExecute(string filePath)
{
	Promise<ProcessResult> promise = new Promise<ProcessResult>();

	ExecuteProcess("chmod", "+x \"" + filePath + "\"")
	.Then(processResult => 
	{
		return ExecuteProcess(promise, filePath);
	})
	.Catch(exception =>
	{
		promise.Reject(exception);
	});

	return promise;
}

But my question is... can I cast this ExecuteProcess method to my already created promise?
Doing something like:
promise = (Promise)ExecuteProcess(filePath); ?
which would give the following code:

public static IPromise<ProcessResult> ChmodAndExecute(string filePath)
{
	Promise<ProcessResult> promise = new Promise<ProcessResult>();

	ExecuteProcess("chmod", "+x \"" + filePath + "\"")
	.Then(processResult => 
	{
		promise = (Promise<ProcessResult>)ExecuteProcess(filePath);
		return promise;
	})
	.Catch(exception =>
	{
		promise.Reject(exception);
	});

	return promise;
}

I tried, but it still does not work :/
PS: Yes, my ExecuteProcess creates a new promise, but also returns it. So if I cast the result of ExecuteProcess, I should now have the new promise inside the promise variable...

Let me know if this is not clear, and thanks in advance!

Yohan

*** can only be called from the main thread

So if you make any interaction with gameObject in "then" it throws simular exception.

sample code:

        public void Start()
        {
            this.Label = gameObject.GetComponent<Text>();
            SOMEFUNCTION.Done(x => this.SetPlayerName());
        }

        private void SetPlayerName()
        {
            this.Label.text = "player name"; // the exception is on this line
        }

exception:

get_isActiveAndEnabled can only be called from the main thread.
Constructors and field initializers will be executed from the loading thread when loading a scene.
Don't use this function in the constructor or field initializers, instead move initialization code to the Awake or Start function.

Support .NET Core

I tried to install RSG.Promise with .NET Core 1.0, but got this error:

Package RSG.Promise 1.2.0 is not compatible with netcoreapp1.0 (.NETCoreApp,Version=v1.0). Package RSG.Promise 1.2.0 supports: net35 (.NETFramework,Version=v3.5)

Best way to add a time out?

Hey there :)

I don't think there is a builtin thing to add a time out to a promise, so how would you do it?
The only thing I can think of right now is after I start my promises, I just do something like TimeOutHelper.RegisterPromise(promise) that will start a coroutine, wait for x seconds, and then reject the coroutine if it's not done.

Thanks!

Run multiple promises, one after the other

Hello again :)

I have this bit of code:

IPromise[] promiseArray = new IPromise[packetCount];
for (int i = 0; i < packetCount; i++)
{
    promiseArray[i] = WriteCharacteristicInternal(byteArray.Skip(i * 20).Take(20).ToArray());
}

return Promise.All(promiseArray);

But as the doc says, it will run all my promises in parallel.
Also, it seems that even if I don't call WriteCharacteristicInternal, it will trigger the promise. So I don't really understand why in the doc it says that Promise.All will run them all in parallel, as they are already started just by calling the WriteCharacteristicInternal method.
Anyway :)
Is there a "native" way of saying that I want to run an array of promises in sequence? Waiting for one to finish, then start the other etc... without having to do that "manually" in multiple .Then?

Thanks!

IL2CPP Problems

Hi all, I've just started using Promises in Unity3d (2017.1) because they look.... promising. I've got a very small test scene running on PS4 compiling with il2cpp, stable .net 3.5, api compat .net 2.0 and no il2cpp optimisation set, the latest promise DLLs from here and I get errors at runtime with this code:

`public class PromiseTest : MonoBehaviour
{
private void Awake()
{
DoThing().Then(b => UnityEngine.Debug.Log("Done: "+b)).Done();
}

private Promise<bool> DoThing()
{
    Promise<bool> p = new Promise<bool>();
    p.Resolve(true);
    return p;
}

}`

Error at runtime:
MissingMethodException: No constructor found for System.Runtime.CompilerServices.StrongBox1[[RSG.Promise1+<>c__DisplayClass61[[System.Boolean, mscorlib, Version=2.0.0.0, Culture=, PublicKeyToken=b77a5c561934e089],[System.Boolean, mscorlib, Version=2.0.0.0, Culture=, PublicKeyToken=b77a5c561934e089]], RSG.Promise, Version=1.1.2.0, Culture=, PublicKeyToken=null]]::.ctor(RSG.Promise1+<>c__DisplayClass61[System.Boolean,System.Boolean])`

I've tried adding
<linker> <assembly fullname="System"> <namespace fullname="System.Runtime.CompilerServices" preserve="all"/> </assembly> <assembly fullname="RSG.Promise"> <namespace fullname="RSG.Promise" preserve="all"/> </assembly> <assembly fullname="RSG.Toolkit"> <namespace fullname="RSG.Utils" preserve="all"/> </assembly> </linker>

to a link.xml file, but still get the same problem. Does anyone know how this might be solved? I've love to use promises for my project.

Multiple async operations cascade

Hello again! Sorry if I post a lot of issues that are just questions :/

I followed the ReadMe but can't find how to do something like this:
Picture.GetListFromId and Tag.GetListFromPicture are both promises.

Picture.GetListFromId(3)
.Then(pictureList =>
{
    for (int i = 0; i < pictureList.Count; i++)
    {
        return Tag.GetListFromPicture(pictureList[i]);
    }
})
.Then(tagList =>
{
});

What I want to achieve, is first get the list of pictures, and then with this list, I want to get the tags for each picture.
So if I have 3 pictures, each having 5 tags, it would:

  • retrieve the list of pictures
  • for each picture retrieve the tag list
  • and trigger the Then(tagList =>) for each picture, so I'll receive 3 time this callback with 3 different list of tags

I don't even know if this is possible...

Also in my example here, I would get a callback with the tagList, but I won't have the pictureList[i] variable that I passed (and I need it) :/

Thanks a lot!

Throwing errors from the Unhandled Exception callback?

Hi,

I am writing unit tests and would like to "expect" an Exception. I thought that if I added a handler for UnhandledException and threw an Exception in the handler it would propagate up into the test but it doesnt seem to, it seems to get caught within the Promise.

Any ideas how I may achieve this?

Cheers,
Mike

Compare with async/await?

Seem like this project do the things that is very similar with MS async/await. So could you tell me what is the differences?

"Resolve" a promise multiple times

Hello again,

Is there to "resolve" a promise multiple times?
Imagine I'm scanning for bluetooth devices, and I use a Promise for that.
I would like to call .Resolve(deviceAddress) every time a new address is found for example, and start another process that will reject the promise after 60sc (to stop scanning).
I don't think there's a way to do that, right?

Promise after Catch should not resolve unless Catch handler returns a value

This is referring to the new functionality in v2.0. It looks like all Catch promises will now resolve, regardless of whether the Catch handler returns a value. I may be missing something, but if that's true I think this is inconsistent with the Promises/A+ spec. The Promises/A+ spec says the following about this (from https://promisesaplus.com/):

2.2.7 then must return a promise [3.3].

 promise2 = promise1.then(onFulfilled, onRejected);

2.2.7.1    If either onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x).
2.2.7.2    If either onFulfilled or onRejected throws an exception e, promise2 must be rejected with e as the reason.

Since onRejected doesn't have to return a value, 2.2.7.1 implies that you could have a situation where promise2 is not resolved. I think the ability to chain promises after a Catch that are not automatically resolved should be present in this Promise library as well.

How can I wait for a promise result in a HttpActionResult method?

Hi there!

What the title says, basically.

I have an HttpActionResult in my API that calls for a method in a Third-party API.
I have the following code:

var aux = thirdPartyApiClient.Model.CreateModel(myModel);
            Model myResult = new Model();
            aux.Catch((exception) => {
                throw new Exception(exception.Message);
            });
            aux.Then((model) =>
            {
                myResult = model;
                //return this.Ok(model.Code);
            });

The problem is - I don't know in the moment how to wait for this result before returning to my application that updated result.

How can I properly wait for this result, for all the method to finish (CreateModel method) before returning something as HttpActionResult?

Running Promises of different Types in Parallel

Is there any way to run Promises of different Types in parallel in the current version that I'm missing?
As it stands it seems like I'm only able to use Promise<T>.Allwith Promises of Type T.

I think it would be useful if there was an overload for Promise.All that took Promises of different types as arguments and returns a Promise<Tuple<T1, T2>> or something.

e.g.

var p1 = Promise<string>.Resolved("str");
var p2 = Promise<int>.Resolved(42);

Promise.All(p1, p2)
  .Done((Tuple<string, int> vals)=>{
    ...
  });

When should we use Done?

Hey :)

Currently I'm using it like this:
Query
.Then
.Then
.Catch
for every request I have.

Is it ok? Or should I do:
Query
.Then
.Then
.Done
.Catch

I'm a little bit confused on what Done is use for, I don't really see the different between this an Then :/

Returning an "empty" promise?

Hey guys!
First of all, thanks a LOT for this super awesome library. Code is so much cleaner thanks to it!

Question:
I have something like that:

Picture.Exists()
.Then(exists =>
{
    if (exists)
    {
        return Picture.Download();
    }
    else
    {
        // What should I do here to finish the promise and not go to the next "Then"?
    }
})
.Then(byteArray =>
{
    // Do something with the byte array
});

My question is in the comment of the code.
If the file does not exists, I don't want to go to the next Then. And the compiler is asking me to return something but... what should I return?

Thanks a lot!

ArgumentException on Catch method and (ab)use of Refletions

I am getting an ArgumentException on Catch at runtime when the promise is Resolved (I think)

ArgumentException: The field handle and the type handle are incompatible.
System.Reflection.FieldInfo.GetFieldFromHandle (RuntimeFieldHandle handle, RuntimeTypeHandle declaringType) (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Reflection/FieldInfo.cs:171)
RSG.Promise1[UnityEngine.GameObject].Catch (System.Action1 onRejected) (at Assets/Lib/CSharpPromises/Promise.cs:431

The error occures on this line in the code

Argument.NotNull(() => onRejected);

and looking at the internals it uses scary machinery like

var value = parameter.Compile().Invoke();

which makes me wonder if this would run on iOS. Commenting the Argument.NotNull makes the code work fine. Why the use of reflection for a Promise library?

Is there a "mother" class common to every promises?

Hello again :)

I have these two methods:

    private IEnumerator TimeOutPromiseCoroutine(Promise promise, float timeOut)
    {
        yield return new WaitForSeconds(timeOut);

        if (promise.CurState == PromiseState.Pending)
        {
            promise.Reject(new Exception("Promise has timed out"));
        }
    }

    private IEnumerator TimeOutPromiseCoroutine(Promise<String[]> promise, float timeOut)
    {
        yield return new WaitForSeconds(timeOut);

        if (promise.CurState == PromiseState.Pending)
        {
            promise.Reject(new Exception("Promise has timed out"));
        }
    }

They are identical, except for the first parameter used.
Is there a way I can use only one method for both cases?

If this is not clear enough, please tell me, I'll explain it in more details.

Exceptions are not caught in Done (in Unity)

If you have a Promise that throws a null reference error in Done, it gets eaten and won't be visible in Unity.

e.g. If you have this field and leave it empty:
[SerializeField] UnityEngine.UI.Image _testImage

And then run a promise like this:

TestPromise()
.Catch(e => Debug.LogException(e))
.Done(_image.color = Color.red);

The body of Done would throw a null reference exception, but it never shows up in Unity's console and it silently stops execution.

Attempt to resolve already rejected promise when combining All and Sequence

I've got a weird situation where I'm getting an exception when my code rejects an asynchronous promise (All) inside a synchronous block (Sequence). The code looks like this:

return GameController.Instance.ApplicationHandshake()
	.Then(() => GameController.Instance.GameHandshake())
	.Then(response => {
		return Promise.Sequence(
			() => Promise.All(
				ContentManager.Instance.LoadAssets(),
				GameController.Instance.Init(response)
					.Then(() => ContinueLoading())
			),
			StartGameInternal);
	});

The ContinueLoading method, which is the cause of the issue (although it seems as though it could also occur if LoadAssets throws an exception) looks like this:

private IPromise ContinueLoading()
{
	var storyUi = UIManager.Instance.SpawnPopup<StorySequenceUI>("ui/story/intro_sequence");
	return storyUi.Init()
		.Then(() => this.splashScreenGO.SetActive(true));
}

To test the issue, I'm explicitly Rejecting in an OnClick handler (we're using Unity) in StorySequenceUI. When I do this, the exception bubbles up properly, but I get a second exception as well:

System.ApplicationException: Attempt to resolve a promise that is already in state: Rejected, a promise can only be resolved when it is still in state: Pending`

Is this because Init in the first Sequence function has already rejected, but LoadAssets is trying to resolve? To be clear, in my case, I'm explicitly Rejecting inside a function called by the GameController.Instance.Init(response).Then(() => ContinueLoading()) block, but ContentManager.Instance.LoadAssets finishes after and resolves properly.

Is this a case where something like ThenRace would be better suited? Maybe I'm totally misunderstanding what is/should be happening here when one of the promises in an All block rejects but the others resolve.

Performance

Hello! This is a great library; thank you for sharing it with everyone.

I'm curious though -- have you guys tested this for mobile games? How is the performance? I haven't tried this library yet, but I imagine that this would take a toll on the GC?

Thanks!

Can't install with Unity v5.2.1f

Hi guys,

I trying to install with Unity v5.2.1f 64bit via nuget and got this error

PM> Install-Package RSG.Promise
Attempting to gather dependencies information for package 'RSG.Promise.1.1.6' with respect to project 'sk2-btf.CSharp', targeting '.NETFramework,Version=v3.5,Profile=Unity Subset v3.5'
Attempting to resolve dependencies for package 'RSG.Promise.1.1.6' with DependencyBehavior 'Lowest'
Resolving actions to install package 'RSG.Promise.1.1.6'
Resolved actions to install package 'RSG.Promise.1.1.6'
Install failed. Rolling back...
Package 'RSG.Promise 1.1.6' does not exist in project 'sk2-btf.CSharp'
Package 'RSG.Promise 1.1.6' does not exist in folder 'D:\bit\sk2-unity3d\src\sk2-btf\packages'
Install-Package : Could not install package 'RSG.Promise 1.1.6'. You are trying to install this 
package into a project that targets '.NETFramework,Version=v3.5,Profile=Unity Subset v3.5', but the 
package does not contain any assembly references or content files that are compatible with that 
framework. For more information, contact the package author.
At line:1 char:1
+ Install-Package RSG.Promise
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
    + FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets 
   .InstallPackageCommand

PM> 

Any hint to make it work please?

Thanks

UnhandledException event fired on promise chain with Catch handler

I'm hitting a snag that I think might be a bug, but it also may just be a misunderstanding on my part.

I have code that adds a handler to Promise UnhandledException event. With that in place, given this simple promise chain:

Promise.Resolved()
    .Then(() => {
        throw new Exception();
    })
    .Catch(ex => { })
    .Done();

I was expecting that the UnhandledException handler would fire because I call Catch, but that appears to not be the case; my UnhandledException handler is fired whether or not I include Catch in the chain. Should the exception stop at Catch? Or will the UnhandledException event always get fired?

I am using version 1.3.0, compiled from GitHub source.

Applying the "try-catch-finally"/"using" patterns

I started using Promises to model asynchronous/pipelined execution flows in our game and I'm really impressed, it just works as I would expect! As I use it e.g. with I/O, I'd like to start a discussion on how to extend the library to work better with C# constructs like "using" and "try-catch-finally".

Try/Catch works (but the Catch method is violating A+ as it cannot return a value/promise) but I struggle to create a good "finally" case. Consider this:

public IPromise Store() 
{
    return Promise.Resolved().Then(() =>
    {
        memoryStream ms = new MemoryStream();
        return StoreImpl(ms);
    });
}

private IPromise StoreImpl(MemoryStream ms)
{
    return Promise.Resolved().Then(() => 
    {
        throw new Exception("That did not work as expected");
    });
}

How would Store() dispose of the MemoryStream when an exception occurs? A Then() callback would not suffice, it would work when the preceding promise resolves, but when it rejects it won't. The disposing code could be duplicated and added as Then() and Catch() callbacks, but by specifying a rejection callback at this point, the exception will not be passed to the client-side error handling. I could explicitely re-throw the exception in a Catch() callback, but that would not preserve the exception per se. The only way I could think of would be to duplicate the disposal code and return another rejecting promise with the same exception, which is currently not possible because the Catch() callbacks can not return a promise (violating the A+ spec):

IPromise Store() 
{
    return Promise.Resolved().Then(() =>
    {
        memoryStream ms = new MemoryStream();

        return StoreImpl(ms)
            .Catch((ex) => {
                ms.Dispose();
                // Currently cannot do this, the rejection handler can not return values but it should
                return Promise.Reject(ex);
            })
            .Then(() => {
                ms.Dispose();
                return Promise.Resolved();
            });
    });
}

What do you think about this? I'll maybe try to fork and fix the Catch() handling myself, but I'd also like to get some feedback on this issue first. Also I'd like to know if there are any other suggestions how finally can be supported more fluently and maybe even how using could be supported in any way!

Suggestion for finally:

  • Implement a IPromise Promise.Finally(Func<IPromise> callback) instance method
  • The callback type of finally does not take any parameters (neither value nor exception!)
  • The Finally callback can return a new promise
  • Finally itself returns a promise
  • The finally callback just sits transparently in the flow of execution, all values/exceptions are passed "around" it and given to the chained handlers

Suggestion for using:

  • Implement static method IPromise Promise.Using(IDisposable, Func<IPromise>)
  • The IDisposable is disposed off when the promise returned by the callback is resolved/rejected, via the new Finally() interface

Basically implemented like this:

static IPromise Using(IDisposable d, Func<IPromise> cb)
{
    return Promise.Resolved().Then(() => {
        return cb();
    }).Finally(() => {
        d.Dispose();
    });
}

I'd love to see this library going forward, as we won't get 4.5 features in unity in the near future and this is a very good alternative!

Add Catch<TException> to IPromise and IPromise<TPromised> interface?

The only difference from a normal Catch is that if the exception does not match the expected type the onRejected handler is not called.

Code that looks like this:

Blackbox.ReturnsPromise()
  .Catch(ex => 
  {
      var specificException = ex as SpecificExceptionType;
      if(ex != null)
      {
          // Handle specific error
      }

      var otherSpecificException = ex as OtherSpecificExceptionType;
      if(otherSpecificException != null)
      {
          // Handle other specific error
      }

      // We didn't handle any of the specific exception types
  }).Then( data => 
  {
      // Do something useful
  });

Then can be written like this:

Blackbox.ReturnsPromise()
  .Catch<SpecificExceptionType>(ex => 
  {
      // Handle specific error
  })
  .Catch<OtherSpecificExceptionType>(ex => 
  {
      // Handle other specific error
  })
  .Catch(ex => 
  {
      // We didn't handle any of the specific exception types
  })
  .Then( data => 
  {
      // Do something useful
  });

The changes required to support this are small. Here is the implementation for the generic promise type.

public IPromise<PromisedT> Catch<TException>(Action<TException> onRejected) 
where TException : Exception
 {
    var resultPromise = new Promise<PromisedT>();
    resultPromise.WithName(Name);
    Action<PromisedT> resolveHandler = v =>
    {
        resultPromise.Resolve(v);
    };

    Action<Exception> rejectHandler = ex =>
    {
        var specificException = ex as TException;
        if (specificException != null)
        {
            onRejected(specificException);
        }

        resultPromise.Reject(ex);
    };

    ActionHandlers(resultPromise, resolveHandler, rejectHandler);

    return resultPromise;
}

Using waitfor and promiseTimer update

Hi I've seen the article on what can go wrong. I'm wanting to replace my StartCorutine that has a yeild waitforseconds in a lateupdate. with Waitfor.

I'm having difficulties understanding how to implement this properly with the example of timed promises in the article.

First is this a mistake? should it be called WaitFor, why is this local function it named after the built in function name?

PromiseTimer promiseTimer = new PromiseTimer();

IPromise WaitFor(float timeToWait)
{
    return promiseTimer.WaitFor(timeToWait);
}

So I have a _promiseTimer.Update(Time.timeDelta) in LateUpdate, I understand that this updates the timer inside PromiseTimer but is it needed? What I am confused with, where to call my waitFor. I don't have anything to watch except time passed. I want to achieve with my promise, after x secs go do the function in the waitfor. Do i just put promise.WairFor(seconds) in LateUpdate.
I know I can assign a promise as a return to the corutine, should I use that approach instead of removing my existing corutine?

thanks

Should throw custom exception types instead of ApplicationException

The Microsoft guidelines recommend against throwing ApplicationException, and throwing a custom type of exception would make it easier for users to distinguish between exceptions thrown by the library and their own code.

So far the only places where this would change anything is where we are attempting to resolve/reject a promise in an invalid state and when Race is called with no promises. If we merge #65 this will add one more case (where progress is updated on an already resolved/rejected promise).

Interrupting a promise sequence from the outside?

I'm trying to interrupt a promise sequence from the outside of the sequence.

I am launching some animations and behaviours that I would like to simply kill if a user decides to go back to the menu. How would I be able to achieve this?

Promise startPromise;

void Start() {
	Invoke ("Test", 0.1f);
	startPromise = Promise.Sequence(
		() => speechBubble.Say(truttaSpeech),
		() => Promise.All(
			ShowMenu(true),
			Promise.Sequence(
				() => phoneContainerUI.Grow (),
				() => phoneUI.Ring(MDRPhoneUI.VIDEO_PATH_STAGE2, 2, false, true)
			)
		)
	).Catch(exception => {
		Debug.Log("PROMISE INTERRUPT WAS CALLED");
	}).Then(() => {
		Debug.Log("PROMISE HAS COMPLETED SUCCESFULLY");
	}) as Promise;

}

void Test() {
	startPromise.Reject (new Exception("Invoke rejection test"));
}

Finally promise resolves even if chain is rejected

To reproduce, consider the following promise chain:

new Promise().Then(() => {
    throw new Exception();
    })
    .Finally(() => {})
    .Then(() => Debug.Print("SUCCESS");
    .Catch(ex =>  Debug.Print("FAILURE");

In version 1.3.0 of this library, I'm seeing SUCCESS and I expect to see FAILURE. It looks like this is because the Finally method resolves the promise it returns in both the Then and Catch handler of the promise it's chaining to...that's not right, is it?

If no, I'm happy to fix and submit a PR.

How does a Promise return control to Unity?

One thing I'm confused about is returning control to Unity after calling a Promise that initiates a coroutine.

I would like my app to remain responsive while I perform a sequence of Promises that are encapsulated within a Coroutine, because the app's UI needs to update an element to indicate the progress of these operations.

Is it possible (or is this a good use case) for RSG.Promises ?
I'm not sure how to proceed, and any input you can provide would be greatly appreciated!

For Xamarin Forms?

Hi, I am trying to use your library in a Xamarin forms application but it does not allow me to add it to a PCL project.
There is no way to use it in this environment?
Thank you

Error when building for Hololens

After building my Unity project for the Hololens this packages breaks.

In the Unity editor it works fine. I included the dll in my assets/packages folder.
I'm using Unity 2017.3.1p1. I also tried installing the package via Nuget, but I still get an error.

Severity	Code	Description	Project	File	Line	Suppression State
Error	CS0012	The type 'IPromise<>' is defined in an assembly that is not referenced. You must add a reference to assembly 'RSG.Promise, Version=3.0.0.0, Culture=neutral, PublicKeyToken=7019fe0722eef3a4'.

iOS issue with UnhandledException handler

I know CSharpPromise has not been tested on iOS. Here's one issue I hit (using the .dlls)

    void Awake() {
        Promise.UnhandledException += LogUnhandledException;
    }

    void LogUnhandledException(object sender, ExceptionEventArgs e)
    {
        Debug.LogErrorFormat("[NetworkManager] Promise had unhandled exception: {0} - {1}", sender, e.Exception);
        Debug.LogException(e.Exception);
    }
ExecutionEngineException: Attempting to JIT compile method '(wrapper managed-to-native) System.Threading.Interlocked:CompareExchange (System.EventHandler`1<RSG.ExceptionEventArgs>&,System.EventHandler`1<RSG.ExceptionEventArgs>,System.EventHandler`1<RSG.ExceptionEventArgs>)' while running with --aot-only.

  at RSG.Promise.add_UnhandledException (System.EventHandler`1 value) [0x00000] in <filename unknown>:0 
  at NetworkManager.Awake () [0x00000] in <filename unknown>:0 

I am on Unity5.1.3 and running on iOS 8

Possible issue when using PomiseTimer.WaitUntil for chains of identical user input

Just started messing around with this library and I believe I have encountered a bug. It's also possible that I am simply misusing the PromiseTimer class.

I have a function that waits for a specified key input from the user and then returns a string

private IPromise<string> WaitForKey(KeyCode inKey)
	{
		Promise<string> promise = new Promise<string>();

		pTimer.WaitUntil(_ => Input.GetKeyDown(inKey))
			.Then(() => promise.Resolve("I just pressed " + inKey.ToString()));

		return promise;
	}

This works as expected as long as I chain together different inputs. but if I ask for the same input twice in a row, they both resolve in the same frame. In the example below all three logs would occur after pressing spacebar a single time.

WaitForKey(KeyCode.Space)
			.Then(result => Debug.Log(result))
			.Then(result => WaitForKey(KeyCode.Space))
			.Then(result => Debug.Log(result))
			.Then(result => Debug.Log("We are all done taking input!!!"));

Is this expected behaviour? If so what would be the proper approach to this example?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.