Closed jacobhzen closed 1 year ago
Yep, I would love that, too. Now itβs official: async/await backward compatible down to iOS 13: https://developer.apple.com/documentation/xcode-release-notes/xcode-13_2-release-notes
This should be as simple as wrapping the send function with withCheckedThrowingContinuation
. Donβt think it applies to the websockets.
This is a good task for a first time contributor. Just create a new file HTTP+async.swift and have two async send functions which wrap their counterparts from the HTTP.swift file.
Correction; We can implement AsyncSequence for web sockets: https://obscuredpixels.com/awaiting-websockets-in-swiftui
But this is not as trivial as the send functions so I would make this a separate issue.
Hi everyone π ,
I am happy to co-work on this feature now that the new version is out. Let me know if anyone wants to give it a try!
@maticzav Sounds interesting! I would like to give it a try π
Tho, seems a lot changed since the initial discussion had kicked off. Please correct me if I'm wrong, but it seems that introducing async/await in the current version's context means extending the following functions with async analogous:
public class Client: GraphQLClient, ObservableObject {
// ...
public func query(
_ args: ExecutionArgs,
request: URLRequest? = nil,
policy: Operation.Policy = .cacheFirst
) -> Source {
// ...
}
// ...
public func mutate(
_ args: ExecutionArgs,
request: URLRequest? = nil,
policy: Operation.Policy = .cacheFirst
) -> Source {
// ...
}
// ...
public func subscribe(
_ args: ExecutionArgs,
request: URLRequest? = nil,
policy: Operation.Policy = .cacheFirst
) -> Source {
// ...
}
}
Also I must note that Combine provides a binding to async/await out-of-box:
let publisher = remoteDataPublisher(forURLs: urls)
for try await data in publisher.values { // AsyncThrowingSequence
...
}
(Source βοΈ Async sequences, streams, and Combine | Swift by Sundell)
That said, it seems that we can extend the Client's API by introducing one-shot throwing async versions of query
and mutate
. As for subscription
we can provide a version that returns AsyncThrowingStream
as out of convenience π€
Please let me know what do you think about it π
@elfenlaid, you are right! Let me know if you are still interested, your comment must have slipped through the cracks of my inbox βΉοΈ
@maticzav yeap, on it then π
I'm so sorry, but I'll park the ticket for now π
for my needs I just created an extension
import struct Foundation.URLRequest
import SwiftGraphQL
import SwiftGraphQLClient
public extension GraphQLClient {
func queryAsync<T, TypeLock>(
_ selection: Selection<T, TypeLock>,
as operationName: String? = nil,
request: URLRequest? = nil,
policy: Operation.Policy = .cacheFirst
) -> AsyncThrowingStream<DecodedOperationResult<T>, any Error> where TypeLock: GraphQLHttpOperation {
query(selection, as: operationName, request: request, policy: policy)
.values
.eraseToThrowingStream()
}
func mutateAsync<T, TypeLock>(
_ selection: Selection<T, TypeLock>,
as operationName: String? = nil,
request: URLRequest? = nil,
policy: Operation.Policy = .cacheFirst
) -> AsyncThrowingStream<DecodedOperationResult<T>, Error> where TypeLock: GraphQLHttpOperation {
mutate(selection, as: operationName, request: request, policy: policy)
.values
.eraseToThrowingStream()
}
func subscribeAsync<T, TypeLock>(
to selection: Selection<T, TypeLock>,
as operationName: String? = nil,
request: URLRequest? = nil,
policy: Operation.Policy = .cacheFirst
) -> AsyncThrowingStream<DecodedOperationResult<T>, Error> where TypeLock: GraphQLWebSocketOperation {
subscribe(to: selection, as: operationName, request: request, policy: policy)
.values
.eraseToThrowingStream()
}
}
For the record, and in case its useful, somehow I thought eraseToThrowingStream()
is part of Swift but I had it in already imported swift-concurrency-extra
packaged:
--
Also note that while in case of mutations arguably cached results should not be used, for queries with policy
set to .cacheAndNetwork
there may be two values returned, see https://github.com/maticzav/swift-graphql/pull/105#discussion_r1348624662
Support for Swift 5.5's new async/await would be amazing.