Repository: napi-rs/napi-rs
File: crates/napi/src/threadsafe_function.rs (Rust)

Code before:
    })
  }

  #[cfg(feature = "tokio_rt")]
  pub async fn call_async<D: 'static + FromNapiValue>(&self, value: Result<T>) -> Result<D> {
    let (sender, receiver) = tokio::sync::oneshot::channel::<Result<D>>();

    self.handle.with_read_aborted(|aborted| {
      if aborted {
        return Err(crate::Error::from_status(Status::Closing));
      }

      check_status!(
        unsafe {
          sys::napi_call_threadsafe_function(
            self.handle.get_raw(),
            Box::into_raw(Box::new(value.map(|data| {
              ThreadsafeFunctionCallJsBackData {
                data,
                call_variant: ThreadsafeFunctionCallVariant::WithCallback,
                callback: Box::new(move |d: Result<JsUnknown>| {
                  sender
                    .send(d.and_then(|d| D::from_napi_value(d.0.env, d.0.value)))
                    .or(Ok(()))
                }),
              }
            })))
            .cast(),
            ThreadsafeFunctionCallMode::NonBlocking.into(),
          )
        },
        "Threadsafe function call_async failed"
      )
    })?;
    receiver
      .await
      .map_err(|_| {
        crate::Error::new(
          Status::GenericFailure,
          "Receive value from threadsafe function sender failed",
        )
      })
      .and_then(|ret| ret)
  }
}

impl<T: 'static> ThreadsafeFunction<T, ErrorStrategy::Fatal> {
  /// See [napi_call_threadsafe_function](https://nodejs.org/api/n-api.html#n_api_napi_call_threadsafe_function)
  /// for more information.
  pub fn call(&self, value: T, mode: ThreadsafeFunctionCallMode) -> Status {
    self.handle.with_read_aborted(|aborted| {

Review comment (suggestion):
Maybe it's worth to add comments here to explain that it's okay to ignore the `send error`

Code after:
    })
  }

  #[cfg(feature = "tokio_rt")]
  pub async fn call_async<D: 'static + FromNapiValue>(&self, value: Result<T>) -> Result<D> {
    let (sender, receiver) = tokio::sync::oneshot::channel::<Result<D>>();

    self.handle.with_read_aborted(|aborted| {
      if aborted {
        return Err(crate::Error::from_status(Status::Closing));
      }

      check_status!(
        unsafe {
          sys::napi_call_threadsafe_function(
            self.handle.get_raw(),
            Box::into_raw(Box::new(value.map(|data| {
              ThreadsafeFunctionCallJsBackData {
                data,
                call_variant: ThreadsafeFunctionCallVariant::WithCallback,
                callback: Box::new(move |d: Result<JsUnknown>| {
                  sender
                    .send(d.and_then(|d| D::from_napi_value(d.0.env, d.0.value)))
                    // The only reason for send to return Err is if the receiver isn't listening
                    // Not hiding the error would result in a napi_fatal_error call, it's safe to ignore it instead.
                    .or(Ok(()))
                }),
              }
            })))
            .cast(),
            ThreadsafeFunctionCallMode::NonBlocking.into(),
          )
        },
        "Threadsafe function call_async failed"
      )
    })?;
    receiver
      .await
      .map_err(|_| {
        crate::Error::new(
          Status::GenericFailure,
          "Receive value from threadsafe function sender failed",
        )
      })
      .and_then(|ret| ret)
  }
}

impl<T: 'static> ThreadsafeFunction<T, ErrorStrategy::Fatal> {
  /// See [napi_call_threadsafe_function](https://nodejs.org/api/n-api.html#n_api_napi_call_threadsafe_function)
  /// for more information.