Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,57 @@ jsi::Value PromiseVendor::createPromise(
return promiseCtor.callAsConstructor(runtime, runPromise);
}

jsi::Value PromiseVendor::createAsyncPromise(
std::function<std::variant<jsi::Value, std::string>(jsi::Runtime &)>
&&function) {
auto &runtime = *runtime_;
auto callInvoker = callInvoker_;
auto promiseCtor = runtime.global().getPropertyAsFunction(runtime, "Promise");
auto promiseLambda = [callInvoker = std::move(callInvoker),
function = std::move(function)](
jsi::Runtime &runtime,
const jsi::Value &thisValue,
const jsi::Value *arguments,
size_t count) -> jsi::Value {
auto resolveLocal = arguments[0].asObject(runtime).asFunction(runtime);
auto resolve = std::make_shared<jsi::Function>(std::move(resolveLocal));
auto rejectLocal = arguments[1].asObject(runtime).asFunction(runtime);
auto reject = std::make_shared<jsi::Function>(std::move(rejectLocal));

/// Here we can swap later for thread pool instead of creating a new thread
/// each time
std::thread(
[callInvoker = std::move(callInvoker),
function = std::move(function),
resolve = std::move(resolve),
reject = std::move(reject)](jsi::Runtime &runtime) {
auto result = function(runtime);
if (std::holds_alternative<jsi::Value>(result)) {
auto valueShared = std::make_shared<jsi::Value>(
std::move(std::get<jsi::Value>(result)));
callInvoker->invokeAsync(
[resolve, &runtime, valueShared]() -> void {
resolve->call(runtime, *valueShared);
});
} else {
auto errorMessage = std::get<std::string>(result);
callInvoker->invokeAsync(
[reject, &runtime, errorMessage]() -> void {
auto error = jsi::JSError(runtime, errorMessage);
reject->call(runtime, error.value());
});
}
},
std::ref(runtime))
.detach();
return jsi::Value::undefined();
};
auto promiseFunction = jsi::Function::createFromHostFunction(
runtime,
jsi::PropNameID::forUtf8(runtime, "asyncPromise"),
2,
std::move(promiseLambda));
return promiseCtor.callAsConstructor(runtime, std::move(promiseFunction));
}

} // namespace audioapi
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <ReactCommon/CallInvoker.h>
#include <jsi/jsi.h>
#include <variant>
#include <thread>
#include <memory>
#include <string>
#include <utility>
Expand Down Expand Up @@ -34,6 +36,23 @@ class PromiseVendor {

jsi::Value createPromise(const std::function<void(std::shared_ptr<Promise>)> &function);

/// @brief Creates an asynchronous promise.
/// @param function The function to execute asynchronously. It should return either a jsi::Value on success or a std::string error message on failure.
/// @return The created promise.
/// @note The function is executed on a different thread, and the promise is resolved or rejected based on the function's outcome.
/// @example
/// ```cpp
/// auto promise = promiseVendor_->createAsyncPromise(
/// [](jsi::Runtime& rt) -> std::variant<jsi::Value, std::string> {
/// // Simulate some heavy work
/// std::this_thread::sleep_for(std::chrono::seconds(2));
/// return jsi::String::createFromUtf8(rt, "Promise resolved successfully!");
/// }
/// );
///
/// return promise;
jsi::Value createAsyncPromise(std::function<std::variant<jsi::Value, std::string>(jsi::Runtime&)> &&function);

private:
jsi::Runtime *runtime_;
std::shared_ptr<react::CallInvoker> callInvoker_;
Expand Down
Loading