# Save Operation

Many methods related to saving and loading return a `SaveOperation<T>` object. The `T`  represents the result type of the operation.

## Working with an Operation

The main purpose of the `SaveOperation` class is to support multithreading. Additionally, it allows you to **register events**, enabling you to receive results or trigger actions precisely when needed.

### Getting the Result

You can get the result of an operation by accessing the Result field.

```csharp
var result = saveOperation.Result;
```

The result is only equal to something after successful completion. See [#recommendation](#recommendation "mention").

### States

You can get the current `State` of the operation with the `state` field.

| Name       | Description                                                                              |
| ---------- | ---------------------------------------------------------------------------------------- |
| NotStarted | The operation has not begun.                                                             |
| Ongoing    | The operation has begun and it has not yet completed.                                    |
| Completed  | The operation has successfully completed.                                                |
| Canceled   | User canceled the operation. An operation can be canceled with `saveOperation.Cancel()`. |
| Failed     | The operation failed. This may happen if an error occurred during the operation.         |

### Events

The recommended way of working with operations is by utilizing the available events.

| Name        | Description                                                                                                             |
| ----------- | ----------------------------------------------------------------------------------------------------------------------- |
| onEnded     | A callback for when the operation has completed, canceled, or failed. Events are cleared after the operation has ended. |
| onCompleted | A callback for when the operation has completed. Events are cleared after the operation has ended.                      |
| onFailed    | A callback for when the operation has failed. Events are cleared after the operation has ended.                         |

You may use the `OnEnd`, `OnComplete`, or `OnFail` methods respectively to register events.

### Recommendation

Below is the recommended scripting pattern to make something happen after the operation has completed while also getting the result. This pattern is recommended because it works no matter what the multithread mode is set to.

{% hint style="warning" %}
NOTE: the `SaveOperation` result type may vary. However, it's usually `SaveState` or `bool`.
{% endhint %}

```csharp
saveOperation.OnComplete(result =>
{
    Debug.Log(result);
});
```

The code is simply logging the result in the console after the operation is successfully completed. You can even chain register events as shown below.

```csharp
saveOperation.OnComplete(result =>
{
    Debug.Log(result);
}).OnFail(() =>
{
    Debug.Log("failed");
});
```

Event registration like this is not necessary if the multithread mode is set to disabled.

## Examples

#### Callbacks

The code below loads a save state and then immediately retrieves data from it.

```csharp
public void Load()
{
    ESave.Load(0).OnComplete(saveState =>
    {
        saveState.GetData<string>("MyDataID").OnComplete(data =>
        {
            Debug.Log(data);
        });
    });
}
```

#### Async Pattern

If you prefer using the async pattern (`async` methods with `await`), you can do the following to achieve the same results as above:

```csharp
public async void Load()
{
    var saveState = await ESave.Load(0).task;
    var data = await saveState.GetData<string>("MyDataID").task;
    Debug.Log(data);
}
```

#### No Multithreading

It's possible to do the same thing in another way, but only if multithread mode is set to disabled.

```csharp
public void Load()
{
    var saveState = ESave.Load(0).Result;
    var data = saveState.GetData<string>("MyDataID");
    Debug.Log(data);
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://espergames.gitbook.io/esave/esave-pro/scripting/save-operation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
