# Usage

# What is a (U-)Promise

A Promise is an awaitable (or yieldable) task thats easy to generate and to use. Additionally if you make your own Promise it's very easy to reject or resolve.

# Using a UPromise

Lets assume we do have a function called DoStuffAsync with the following signature:

    public IPromise DoStuffAsync();

And a function called GetStuffAsync with the following signature:

    public IPromise<string> GetStuffAsync();

# Using Promises with async/await

The main way to use promises is surely to use async/await.

You can call a method marked with the async keyword like any other function in Unity.

    public void OnButtonPress()
    {
        Debug.Log("Before the Async function");
        AsyncFunction();
        Debug.Log("Called while the Async function is still running");
    }

However inside the function you can use the await keyword to wait for the completion of another async function and potentially getting back their return value.

    public async void AsyncFunction(){
        Debug.Log("Before the Async function");
        await DoStuffAsync();
        Debug.Log("After the Async function");

        string myValue = await GetStuffAsync();
        Debug.Log("I got the value: "+myValue);
    }

# Using Promises with CoRoutines

To make the change for everyone easier we also implemented a way to use Promises in combination with the default unity way of async operations: CoRoutines

    public void OnButtonPress()
    {
        Debug.Log("Before the CoRoutine");
        StartCoroutine(MyCoroutine());
        Debug.Log("Called while the CoRoutine is still running");
    }

    public IEnumerator MyCoroutine()
    {
        Debug.Log("CoRoutine started");
        yield return DoStuffAsync();
        Debug.Log("CoRoutine waited for the async stuff and is now stopping");
    }

As you can see you can just directly yield the promise like other built-in classes (like WaitForSeconds for example).

You can also retrieve back values from the promise, however this is a bit more complicated and not recommended in combination with CoRoutines.

    public void OnButtonPress()
    {
        Debug.Log("Before the CoRoutine");
        StartCoroutine(MyCoroutine());
        Debug.Log("Called while the CoRoutine is still running");
    }

    public IEnumerator MyCoroutine()
    {
        Debug.Log("CoRoutine started");
        var promise = GetStuffAsync();
        yield return promise;
        Debug.Log("CoRoutine waited for the async stuff and retrieved: " + promise.Task.Result);
    }

# Using Progress Promises

Additionally to the normal Promises from above we also offer you promises that can report back progress.

    public void DownloadData()
    {
        var promise = Promise.From(UnityWebRequest.Get("http://fivefingergames.com"));
        promise.OnProgress += (sender, progress) => {
            uiDownloadProgress.text = (progress*100).ToString("F0")+"%";
        }
        promise.OnCompleted += () => {
            uiDownloadProgress.text = "Download finished. Click to Start";
        }
    }

# Combining Promises

You are also flexible to combine different Promises into a new Promise by using the following methods.

# All

All combines two or more promises into a new promise that is resolved once all promises are resolved.

    public async void DownloadAll(){
        var promise1 = Promise.From(UnityWebRequest.Get("http://fivefingergames.com/text1"));
        var promise2 = Promise.From(UnityWebRequest.Get("http://fivefingergames.com/text2"));
        await Promise.All(promise1, promise2);
        var text1 = promise1.Result;
        var text2 = promise2.Result;
    }

# Race

Combines two or more promises into a new Promise that will be resolved once any of the promises are resolved. It will return the promise that finished first.

WARNING

It doesn't stop the other promises.

    public async void DownloadWithTimeout(){
        var promise1 = Promise.From(UnityWebRequest.Get("http://fivefingergames.com/text1"));
        var promise2 = Promise.Delay(10000);
        var finishedPromise = await Promise.Race(promise1, promise2);
        if(finishedPromise == promise1){
            // Use data from the WebRequest
        }else if (finishedPromise == promise2){
            // WebRequest didn't finish in time
        }
    }

# Creating Promises

# Creating a custom Promise

class Arrow: MonoBehaviour{
    public Promise<Collider> wait4Hit;

    public Promise<collider> FireProjectile()
    {
        Debug.Log("Creating the Promise");
        wait4Hit = new Promise<Collider>();

        Debug.Log("Firing Projectile");
        GetComponent<Rigidbody>().AddForce(new Vector3(1000,0,0));

        return wait4Hit;
    }
    public void OnTriggerEnter(Collider collider){
        wait4Hit.Resolve(collider);
    }
}

In the above example we can fire an arrow (using the FireProjectile method of the arrow). The method creates the promise wait4Hit and stores it in a field of the arrow class. It also adds some force to the rigidbody and then returns the promise. The promise is later resolved once the arrow collides with something.

In the calling class we can now do the following:

    public async void ShootEnemy()
    {
        var arrow = Instantiate(ArrowPrefab);
        var enemy = await arrow.GetComponent<Arrow>().FireProjectile();
        Debug.Log("The enemy "+enemy.name+" was hit!");
    }
}

We cann call the FireProjectile Method and we get back a promise. We immmediatly await the promise which means that once the promise is resolved we can get back the enemy we hit and do something with it.

# Creating a Promise with DoTween

Another example in combination with the famous DoTween plugin:

    public async void OnButtonPress()
    {
        Debug.Log("Will be executed before the Camera is rotated");
        await RotateCameraAsync(Quaternion.identity);
        Debug.Log("Will be executed after the Camera finished it's rotation");
    }
    public IPromise RotateCameraAsync(Quaternion targetRotation)
    {
        return new Promise(promise => {
            transform.DORotate(targetRotation.eulerAngles, 0.5f)
                .OnComplete(() => promise.Resolve());

            DOTween.Play(transform);
        });
    }

Here we are using the js-like constructor of a promise. We can give a lamda (or function) which recieves the promise as an parametern and which sets up a callback to resolve the promise.

Of course this is just an example and you can use any kind of callback to resolve the Promise.

# Create a Promise that will resolve after a specific Time

For convenience we made a util method that will return a ready made promise.

    var promise = Promise.Delay(100);
    var promise = Promise.Delay(TimeSpan.FromMilliseconds(100));

Both promises will resolved automatically after 100 ms have passed.

# Create Promises that will resolve immediatly

    var promise = Promise.Resolved();
    var promise = Promise<string>.Resolved("test");

# Create a Promise that will resolve once a condition is met

    var promise = Promise.Until( () => _navAgent.remainingDistance <= _navAgent.stoppingDistance);

# Create a Promise that will resolve once a condition is no longer met

    var promise = Promise.Until( () => _navAgent.remainingDistance > _navAgent.stoppingDistance);

# Create a Promise that will resolve once a (unity ui) button is pressed

    var promise = Promise.From(button);

# Create a ProgressPromise that will resolve once a UnityWebRequest completed

    var promise = Promise.From(UnityWebRequest.Get("http://fivefingergames.com"));

# Create a ProgressPromise that is resolved once a AssetBundleRequest finished loading

    var promise = Promise.From(assetBundle.LoadAssetAsync("MyAsset"));