2024-09-15 16:15:26 +08:00
|
|
|
#ifndef __PROMISEHANDLER_H__
|
|
|
|
#define __PROMISEHANDLER_H__
|
|
|
|
|
|
|
|
#include "../FunctionTraits.h"
|
|
|
|
#include "PromiseData.h"
|
2024-09-15 23:39:23 +08:00
|
|
|
#include <exception>
|
|
|
|
#include <type_traits>
|
2024-09-15 16:15:26 +08:00
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
class Promise;
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct PromiseDeduce {
|
|
|
|
using Type = Promise<T>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct PromiseDeduce<T &> : public PromiseDeduce<T> {};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct PromiseDeduce<const T> : public PromiseDeduce<T> {};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct PromiseDeduce<const volatile T> : public PromiseDeduce<T> {};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct PromiseDeduce<Promise<T>> : public PromiseDeduce<T> {};
|
|
|
|
|
2024-09-15 23:39:23 +08:00
|
|
|
template <typename Functor, typename... Args>
|
|
|
|
struct PromiseFunctor {
|
|
|
|
using ResultType = typename std::invoke_result_t<Functor, Args...>;
|
|
|
|
using PromiseType = typename PromiseDeduce<ResultType>::Type;
|
|
|
|
};
|
|
|
|
|
2024-09-15 16:15:26 +08:00
|
|
|
template <typename T>
|
|
|
|
struct PromiseFulfill {
|
|
|
|
template <typename V, typename TResolve, typename TReject>
|
|
|
|
static void call(V &&value, const TResolve &resolve, const TReject &) {
|
|
|
|
resolve(std::forward<V>(value));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct PromiseFulfill<Promise<T>> {
|
|
|
|
template <typename TResolve, typename TReject>
|
|
|
|
static void call(const Promise<T> &promise, const TResolve &resolve, const TReject &reject) {
|
|
|
|
if (promise.isFulfilled()) {
|
|
|
|
resolve(promise.m_d->value());
|
|
|
|
} else if (promise.isRejected()) {
|
|
|
|
reject(promise.m_d->error());
|
|
|
|
} else {
|
|
|
|
promise.then([=]() { resolve(promise.m_d->value()); },
|
|
|
|
[=]() { // catch all
|
|
|
|
reject(promise.m_d->error());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct PromiseFulfill<Promise<void>> {
|
|
|
|
template <typename TPromise, typename TResolve, typename TReject>
|
|
|
|
static void call(const TPromise &promise, const TResolve &resolve, const TReject &reject) {
|
|
|
|
if (promise.isFulfilled()) {
|
|
|
|
resolve();
|
|
|
|
} else if (promise.isRejected()) {
|
|
|
|
reject(promise.m_d->error());
|
|
|
|
} else {
|
|
|
|
promise.then([=]() { resolve(); },
|
|
|
|
[=]() { // catch all
|
|
|
|
reject(promise.m_d->error());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename Result>
|
|
|
|
struct PromiseDispatch {
|
|
|
|
template <typename Resolve, typename Reject, typename Functor, typename... Args>
|
|
|
|
static void call(const Resolve &resolve, const Reject &reject, Functor fn, Args &&...args) {
|
|
|
|
try {
|
|
|
|
PromiseFulfill<std::decay_t<Result>>::call(fn(std::forward<Args>(args)...), resolve, reject);
|
|
|
|
} catch (...) {
|
|
|
|
reject(std::current_exception());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct PromiseDispatch<void> {
|
|
|
|
template <typename Resolve, typename Reject, typename Functor, typename... Args>
|
|
|
|
static void call(const Resolve &resolve, const Reject &reject, Functor fn, Args &&...args) {
|
|
|
|
try {
|
|
|
|
fn(std::forward<Args>(args)...);
|
|
|
|
resolve();
|
|
|
|
} catch (...) {
|
|
|
|
reject(std::current_exception());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T, typename THandler, typename TArg = typename ArgsOf<THandler>::first>
|
|
|
|
struct PromiseHandler {
|
|
|
|
using ResType = std::invoke_result_t<THandler, T>;
|
|
|
|
using PromiseType = typename PromiseDeduce<ResType>::Type;
|
|
|
|
|
|
|
|
template <typename TResolve, typename TReject>
|
|
|
|
static std::function<void(const T &)> create(const THandler &handler, const TResolve &resolve, const TReject &reject) {
|
|
|
|
return [=](const T &value) { PromiseDispatch<ResType>::call(resolve, reject, handler, value); };
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T, typename THandler>
|
|
|
|
struct PromiseHandler<T, THandler, void> {
|
|
|
|
using ResType = std::invoke_result_t<THandler>;
|
|
|
|
using PromiseType = typename PromiseDeduce<ResType>::Type;
|
|
|
|
|
|
|
|
template <typename TResolve, typename TReject>
|
|
|
|
static std::function<void(const T &)> create(const THandler &handler, const TResolve &resolve, const TReject &reject) {
|
|
|
|
return [=](const T &) { PromiseDispatch<ResType>::call(resolve, reject, handler); };
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename THandler>
|
|
|
|
struct PromiseHandler<void, THandler, void> {
|
|
|
|
using ResType = std::invoke_result_t<THandler>;
|
|
|
|
using PromiseType = typename PromiseDeduce<ResType>::Type;
|
|
|
|
|
|
|
|
template <typename TResolve, typename TReject>
|
|
|
|
static std::function<void()> create(const THandler &handler, const TResolve &resolve, const TReject &reject) {
|
|
|
|
return [=]() { PromiseDispatch<ResType>::call(resolve, reject, handler); };
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct PromiseHandler<T, std::nullptr_t, void> {
|
|
|
|
using PromiseType = Promise<T>;
|
|
|
|
|
|
|
|
template <typename TResolve, typename TReject>
|
|
|
|
static std::function<void(const T &)> create(std::nullptr_t, const TResolve &resolve, const TReject &reject) {
|
|
|
|
return [=](const T &value) {
|
|
|
|
// 2.2.7.3. If onFulfilled is not a function and promise1 is fulfilled,
|
|
|
|
// promise2 must be fulfilled with the same value as promise1.
|
|
|
|
PromiseFulfill<T>::call(std::move(T(value)), resolve, reject);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct PromiseHandler<void, std::nullptr_t, void> {
|
|
|
|
using PromiseType = Promise<void>;
|
|
|
|
|
|
|
|
template <typename TResolve, typename TReject>
|
|
|
|
static std::function<void()> create(std::nullptr_t, const TResolve &resolve, const TReject &) {
|
|
|
|
return [=]() {
|
|
|
|
// 2.2.7.3. If onFulfilled is not a function and promise1 is fulfilled,
|
|
|
|
// promise2 must be fulfilled with the same value as promise1.
|
|
|
|
resolve();
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T, typename THandler, typename TArg = typename ArgsOf<THandler>::first>
|
|
|
|
struct PromiseCatcher {
|
|
|
|
using ResType = std::invoke_result_t<THandler, TArg>;
|
|
|
|
|
|
|
|
template <typename TResolve, typename TReject>
|
|
|
|
static std::function<void(const PromiseError &)> create(const THandler &handler, const TResolve &resolve, const TReject &reject) {
|
|
|
|
return [=](const PromiseError &error) {
|
|
|
|
try {
|
|
|
|
error.rethrow();
|
|
|
|
} catch (const TArg &argError) {
|
|
|
|
PromiseDispatch<ResType>::call(resolve, reject, handler, argError);
|
|
|
|
} catch (...) {
|
|
|
|
reject(std::current_exception());
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T, typename THandler>
|
|
|
|
struct PromiseCatcher<T, THandler, void> {
|
|
|
|
using ResType = typename std::invoke_result_t<THandler>;
|
|
|
|
|
|
|
|
template <typename TResolve, typename TReject>
|
|
|
|
static std::function<void(const PromiseError &)> create(const THandler &handler, const TResolve &resolve, const TReject &reject) {
|
|
|
|
return [=](const PromiseError &error) {
|
|
|
|
try {
|
|
|
|
error.rethrow();
|
|
|
|
} catch (...) {
|
|
|
|
PromiseDispatch<ResType>::call(resolve, reject, handler);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct PromiseCatcher<T, std::nullptr_t, void> {
|
|
|
|
template <typename TResolve, typename TReject>
|
|
|
|
static std::function<void(const PromiseError &)> create(std::nullptr_t, const TResolve &, const TReject &reject) {
|
|
|
|
return [=](const PromiseError &error) {
|
|
|
|
// 2.2.7.4. If onRejected is not a function and promise1 is rejected,
|
|
|
|
// promise2 must be rejected with the same reason as promise1
|
|
|
|
reject(error);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // __PROMISEHANDLER_H__
|