123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- /*
- * Copyright (c) 2021, Kyle Pereira <hey@xylepereira.me>
- * Copyright (c) 2022, kleines Filmröllchen <filmroellchen@serenityos.org>
- * Copyright (c) 2021-2023, Ali Mohammad Pur <mpfard@serenityos.org>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #pragma once
- #include <AK/Concepts.h>
- #include <LibCore/EventLoop.h>
- #include <LibCore/EventReceiver.h>
- namespace Core {
- template<typename Result, typename TError>
- class Promise : public EventReceiver {
- C_OBJECT(Promise);
- public:
- using ErrorType = TError;
- Function<ErrorOr<void>(Result&)> on_resolution;
- Function<void(ErrorType&)> on_rejection;
- void resolve(Result&& result)
- {
- m_result_or_rejection = move(result);
- if (on_resolution) {
- auto handler_result = on_resolution(m_result_or_rejection->value());
- possibly_handle_rejection(handler_result);
- }
- }
- void reject(ErrorType&& error)
- {
- m_result_or_rejection = move(error);
- possibly_handle_rejection(*m_result_or_rejection);
- }
- bool is_rejected()
- {
- return m_result_or_rejection.has_value() && m_result_or_rejection->is_error();
- }
- bool is_resolved() const
- {
- return m_result_or_rejection.has_value() && !m_result_or_rejection->is_error();
- }
- ErrorOr<Result, ErrorType> await()
- {
- while (!m_result_or_rejection.has_value())
- Core::EventLoop::current().pump();
- return m_result_or_rejection.release_value();
- }
- // Converts a Promise<A> to a Promise<B> using a function func: A -> B
- template<typename T>
- NonnullRefPtr<Promise<T>> map(Function<T(Result&)> func)
- {
- NonnullRefPtr<Promise<T>> new_promise = Promise<T>::construct();
- if (is_resolved())
- new_promise->resolve(func(m_result_or_rejection->value()));
- if (is_rejected())
- new_promise->reject(m_result_or_rejection->release_error());
- on_resolution = [new_promise, func = move(func)](Result& result) -> ErrorOr<void> {
- new_promise->resolve(func(result));
- return {};
- };
- on_rejection = [new_promise](ErrorType& error) {
- new_promise->reject(move(error));
- };
- return new_promise;
- }
- template<CallableAs<void, Result&> F>
- Promise& when_resolved(F handler)
- {
- return when_resolved([handler = move(handler)](Result& result) -> ErrorOr<void> {
- handler(result);
- return {};
- });
- }
- template<CallableAs<ErrorOr<void>, Result&> F>
- Promise& when_resolved(F handler)
- {
- on_resolution = move(handler);
- if (is_resolved()) {
- auto handler_result = on_resolution(m_result_or_rejection->value());
- possibly_handle_rejection(handler_result);
- }
- return *this;
- }
- template<CallableAs<void, ErrorType&> F>
- Promise& when_rejected(F handler)
- {
- on_rejection = move(handler);
- if (is_rejected())
- on_rejection(m_result_or_rejection->error());
- return *this;
- }
- private:
- template<typename T>
- void possibly_handle_rejection(ErrorOr<T>& result)
- {
- if (result.is_error() && on_rejection)
- on_rejection(result.error());
- }
- Promise() = default;
- Promise(EventReceiver* parent)
- : EventReceiver(parent)
- {
- }
- Optional<ErrorOr<Result, ErrorType>> m_result_or_rejection;
- };
- }
|