# `HTTP.Promise`
[🔗](https://github.com/gsmlg-dev/http_fetch/blob/v0.21.17/apps/http_fetch/lib/http/promise.ex#L1)

JavaScript-like Promise implementation for asynchronous HTTP operations.

This module provides a Promise-based interface for handling asynchronous HTTP
requests, wrapping Elixir's `Task` with familiar Promise semantics including
chaining via `then/3` and error handling.

## Features

- **Async/await pattern**: Similar to JavaScript's Promise.await()
- **Promise chaining**: Chain operations with `then/3` for sequential async operations
- **Error handling**: Separate success and error callbacks
- **Task-based**: Built on Elixir's Task.Supervisor for reliability

## Basic Usage

    # Simple await
    response =
      HTTP.fetch("https://api.example.com/data")
      |> HTTP.Promise.await()

    # Promise chaining
    HTTP.fetch("https://api.example.com/users/1")
    |> HTTP.Promise.then(&HTTP.Response.json/1)
    |> HTTP.Promise.then(fn {:ok, user} ->
      IO.puts("User: " <> user["name"])
    end)
    |> HTTP.Promise.await()

## Chaining with Error Handling

    HTTP.fetch("https://api.example.com/data")
    |> HTTP.Promise.then(
      fn response -> HTTP.Response.json(response) end,
      fn error -> {:error, :request_failed} end
    )
    |> HTTP.Promise.await()

## Returning Promises from Callbacks

Callbacks in `then/3` can return another Promise, enabling sequential async operations:

    HTTP.fetch("https://api.example.com/posts/1")
    |> HTTP.Promise.then(fn response ->
      {:ok, post} = HTTP.Response.json(response)
      # Fetch comments for this post
      HTTP.fetch("https://api.example.com/posts/1/comments")
    end)
    |> HTTP.Promise.then(fn comments_response ->
      HTTP.Response.json(comments_response)
    end)
    |> HTTP.Promise.await()

# `error_callback_fun`

```elixir
@type error_callback_fun() :: (term() -&gt; any())
```

# `success_callback_fun`

```elixir
@type success_callback_fun() :: (HTTP.Response.t() -&gt; any())
```

# `t`

```elixir
@type t() :: %HTTP.Promise{
  completion: HTTP.RequestCompletion.t() | nil,
  task: Task.t()
}
```

# `await`

```elixir
@spec await(t(), timeout :: non_neg_integer() | :infinity) ::
  HTTP.Response.t() | {:error, term()}
```

Awaits the completion of the HTTP promise.

Arguments:
  - `promise`: The `HTTP.Promise` instance to await.
  - `timeout`: Optional timeout in milliseconds or `:infinity`. Defaults to `:infinity`.

Returns:
  - `%HTTP.Response{}` on successful completion.
  - `{:error, reason}` if the request fails or is aborted.
  - `{:error, :timeout}` if the timeout is reached.

# `completion`

```elixir
@spec completion(t()) :: HTTP.RequestCompletion.t() | nil
```

Returns the original request's cleanup handle. Chained promises return nil.

# `then`

```elixir
@spec then(t(), success_callback_fun(), error_callback_fun() | nil) :: t()
```

Attaches callbacks for the resolution or rejection of the Promise.
Returns a new `HTTP.Promise` for chaining.

Arguments:
  - `promise`: The current `HTTP.Promise` instance.
  - `success_fun`: A 1-arity function to be called if the promise resolves successfully.
                   It receives the `HTTP.Response.t()` as an argument.
                   Can return a value, `{:ok, value}`, `{:error, reason}`, or another `HTTP.Promise`.
  - `error_fun`: An optional 1-arity function to be called if the promise is rejected.
                 It receives the reason for rejection as an argument.
                 Can return a value, `{:ok, value}`, `{:error, reason}`, or another `HTTP.Promise`.

Returns:
  - `%HTTP.Promise{}`: A new promise representing the outcome of the callbacks.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
