sendRequest<R> method

  1. @override
FutureOr<R?> sendRequest<R>(
  1. Uri uri, {
  2. DataRequestMethod method = DataRequestMethod.GET,
  3. Map<String, String>? headers,
  4. bool omitDefaultParams = false,
  5. DataRequestType requestType = DataRequestType.adhoc,
  6. String? key,
  7. String? body,
  8. OnRawData<R>? onSuccess,
  9. OnDataError<R>? onError,
})
inherited

The function used to perform an HTTP request and return an R.

IMPORTANT:

  • uri takes the FULL Uri including query parameters
  • headers does NOT include ANY defaults such as defaultHeaders (unless you omit the argument, in which case defaults will be included)

Example:

await sendRequest(
  baseUrl.asUri + 'token' & await defaultParams & {'a': 1},
  headers: await defaultHeaders & {'a': 'b'},
  onSuccess: (data) => data['token'] as String,
);

ignore: comment_references To build the URI you can use String.asUri, Uri.+ and Uri.&.

To merge headers and params with their defaults you can use the helper Map<String, dynamic>.&.

In addition, onSuccess is supplied to post-process the data in JSON format. Deserialization and initialization typically occur in this function.

onError can also be supplied to override _RemoteAdapter.onError.

Implementation

@override
FutureOr<R?> sendRequest<R>(
  final Uri uri, {
  DataRequestMethod method = DataRequestMethod.GET,
  Map<String, String>? headers,
  bool omitDefaultParams = false,
  DataRequestType requestType = DataRequestType.adhoc,
  String? key,
  String? body,
  OnRawData<R>? onSuccess,
  OnDataError<R>? onError,
}) async {
  // default key to type#s3mth1ng
  final offlineKey = key ?? DataHelpers.generateKey(internalType);
  assert(offlineKey.startsWith(internalType));

  // execute request
  return await super.sendRequest<R>(
    uri,
    method: method,
    headers: headers,
    requestType: requestType,
    omitDefaultParams: omitDefaultParams,
    key: key,
    body: body,
    onSuccess: (data) {
      // remove all operations with this
      // requestType/offlineKey metadata
      OfflineOperation<T>(
        requestType: requestType,
        offlineKey: offlineKey,
        request: '${method.toShortString()} $uri',
        body: body,
        headers: headers,
        onSuccess: onSuccess,
        onError: onError,
        adapter: this,
      ).remove();

      // yield
      return onSuccess?.call(data);
    },
    onError: (e) {
      if (isNetworkError(e.error)) {
        // queue a new operation if this is
        // a network error and we're offline
        OfflineOperation<T>(
          requestType: requestType,
          offlineKey: offlineKey,
          request: '${method.toShortString()} $uri',
          body: body,
          headers: headers,
          onSuccess: onSuccess,
          onError: onError,
          adapter: this,
        ).add();

        // wrap error in an OfflineException
        e = OfflineException(error: e.error);

        // call error handler but do not return it
        (onError ?? this.onError).call(e);

        // instead return a fallback model
        switch (requestType) {
          case DataRequestType.findAll:
            return findAll(remote: false, syncLocal: false) as Future<R>;
          case DataRequestType.findOne:
          case DataRequestType.save:
            // call without type (ie 3 not users#3)
            // key! as we know findOne does pass it
            return findOne(key!.detypify(), remote: false) as Future<R?>;
          default:
            return null;
        }
      }

      // if it was not a network error

      // remove all operations with this
      // requestType/offlineKey metadata
      OfflineOperation<T>(
        requestType: requestType,
        offlineKey: offlineKey,
        request: '${method.toShortString()} $uri',
        body: body,
        headers: headers,
        onSuccess: onSuccess,
        onError: onError,
        adapter: this,
      ).remove();

      // return handler call
      return (onError ?? this.onError).call(e);
    },
  );
}