Skip to content

Commit 9160417

Browse files
authored
Merge pull request #350 from boxdot/async-await
Use async/await and exclusively futures 0.3.
2 parents 23f484e + b2e7070 commit 9160417

File tree

14 files changed

+112
-154
lines changed

14 files changed

+112
-154
lines changed

examples/github/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ edition = "2018"
88
anyhow = "1.0"
99
graphql_client = { path = "../../graphql_client" }
1010
serde = "^1.0"
11-
reqwest = "^0.9"
11+
reqwest = { version = "^0.10", features = ["json", "blocking"] }
1212
prettytable-rs = "^0.7"
1313
structopt = "^0.3"
1414
dotenv = "^0.13"

examples/github/examples/github.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ fn main() -> Result<(), anyhow::Error> {
5151
name: name.to_string(),
5252
});
5353

54-
let client = reqwest::Client::new();
54+
let client = reqwest::blocking::Client::new();
5555

56-
let mut res = client
56+
let res = client
5757
.post("https://api.github.com/graphql")
5858
.bearer_auth(config.github_api_token)
5959
.json(&q)

examples/hasura/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ graphql_client = { path = "../../graphql_client" }
1010
serde = "1.0"
1111
serde_derive = "1.0"
1212
serde_json = "1.0"
13-
reqwest = "^0.9.0"
13+
reqwest = { version = "^0.10", features = ["json", "blocking"] }
1414
prettytable-rs = "0.7.0"
1515
dotenv = "0.13.0"
1616
log = "0.4.3"

examples/hasura/examples/hasura.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ fn main() -> Result<(), anyhow::Error> {
2929
update_columns: vec![Name, Status, SalesforceUpdatedAt],
3030
});
3131

32-
let client = reqwest::Client::new();
32+
let client = reqwest::blocking::Client::new();
3333

34-
let mut res = client
34+
let res = client
3535
.post("https://localhost:8080/v1/graphql")
3636
.json(&q)
3737
.send()?;

examples/web/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ wasm-bindgen = "^0.2"
1515
serde = { version = "1.0.67", features = ["derive"] }
1616
lazy_static = "1.0.1"
1717
js-sys = "0.3.6"
18-
futures = "0.1.25"
19-
wasm-bindgen-futures = "0.3.6"
18+
futures-util = "0.3.8"
19+
wasm-bindgen-futures = "0.4.18"
2020

2121
[dev-dependencies.web-sys]
2222
version = "0.3.6"

examples/web/examples/web.rs

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use futures::Future;
21
use graphql_client::GraphQLQuery;
32
use lazy_static::*;
43
use std::cell::RefCell;
@@ -23,28 +22,23 @@ lazy_static! {
2322
static ref LAST_ENTRY: Mutex<RefCell<Option<String>>> = Mutex::new(RefCell::new(None));
2423
}
2524

26-
fn load_more() -> impl Future<Item = JsValue, Error = JsValue> {
25+
async fn load_more() -> Result<JsValue, JsValue> {
2726
let client = graphql_client::web::Client::new("https://www.graphqlhub.com/graphql");
2827
let variables = puppy_smiles::Variables {
2928
after: LAST_ENTRY
3029
.lock()
3130
.ok()
3231
.and_then(|opt| opt.borrow().to_owned()),
3332
};
34-
let response = client.call(PuppySmiles, variables);
35-
36-
response
37-
.map(|response| {
38-
render_response(response);
39-
JsValue::NULL
40-
})
41-
.map_err(|err| {
42-
log(&format!(
43-
"Could not fetch puppies. graphql_client_web error: {:?}",
44-
err
45-
));
46-
JsValue::NULL
47-
})
33+
let response = client.call(PuppySmiles, variables).await.map_err(|err| {
34+
log(&format!(
35+
"Could not fetch puppies. graphql_client_web error: {:?}",
36+
err
37+
));
38+
JsValue::NULL
39+
})?;
40+
render_response(response);
41+
Ok(JsValue::NULL)
4842
}
4943

5044
fn document() -> web_sys::Document {

graphql_client/Cargo.toml

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@ graphql_query_derive = { path = "../graphql_query_derive", version = "0.9.0", op
1717
serde_json = "1.0"
1818
serde = { version = "^1.0.78", features = ["derive"] }
1919

20-
[dependencies.futures]
21-
version = "^0.1"
22-
optional = true
23-
2420
[dependencies.js-sys]
2521
version = "^0.3"
2622
optional = true
@@ -39,22 +35,18 @@ version = "^0.2"
3935
optional = true
4036

4137
[dependencies.wasm-bindgen-futures]
42-
version = "^0.3"
38+
version = "^0.4"
4339
optional = true
4440

45-
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
46-
reqwest = "^0.9"
47-
4841
[dev-dependencies]
4942
# Note: If we bumpup wasm-bindge-test version, we should change CI setting.
50-
wasm-bindgen-test = "^0.2"
43+
wasm-bindgen-test = "^0.3"
5144

5245
[features]
5346
default = ["graphql_query_derive"]
5447
web = [
5548
"anyhow",
5649
"thiserror",
57-
"futures",
5850
"js-sys",
5951
"log",
6052
"wasm-bindgen",

graphql_client/src/web.rs

Lines changed: 43 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
//! [wasm-bindgen](https://github.com/rustwasm/wasm-bindgen).
33
44
use crate::*;
5-
use futures::{Future, IntoFuture};
65
use log::*;
76
use std::collections::HashMap;
87
use thiserror::*;
@@ -75,71 +74,56 @@ impl Client {
7574
///
7675
// Lint disabled: We can pass by value because it's always an empty struct.
7776
#[allow(clippy::needless_pass_by_value)]
78-
pub fn call<Q: GraphQLQuery + 'static>(
77+
pub async fn call<Q: GraphQLQuery + 'static>(
7978
&self,
8079
_query: Q,
8180
variables: Q::Variables,
82-
) -> impl Future<Item = crate::Response<Q::ResponseData>, Error = ClientError> + 'static {
83-
// this can be removed when we convert to async/await
84-
let endpoint = self.endpoint.clone();
85-
let custom_headers = self.headers.clone();
81+
) -> Result<crate::Response<Q::ResponseData>, ClientError> {
82+
let window = web_sys::window().ok_or_else(|| ClientError::NoWindow)?;
83+
let body =
84+
serde_json::to_string(&Q::build_query(variables)).map_err(|_| ClientError::Body)?;
8685

87-
web_sys::window()
88-
.ok_or_else(|| ClientError::NoWindow)
89-
.into_future()
90-
.and_then(move |window| {
91-
serde_json::to_string(&Q::build_query(variables))
92-
.map_err(|_| ClientError::Body)
93-
.map(move |body| (window, body))
94-
})
95-
.and_then(move |(window, body)| {
96-
let mut request_init = web_sys::RequestInit::new();
97-
request_init
98-
.method("POST")
99-
.body(Some(&JsValue::from_str(&body)));
86+
let mut request_init = web_sys::RequestInit::new();
87+
request_init
88+
.method("POST")
89+
.body(Some(&JsValue::from_str(&body)));
10090

101-
web_sys::Request::new_with_str_and_init(&endpoint, &request_init)
102-
.map_err(|_| ClientError::JsException)
103-
.map(|request| (window, request))
104-
// "Request constructor threw");
105-
})
106-
.and_then(move |(window, request)| {
107-
let headers = request.headers();
108-
headers
109-
.set("Content-Type", "application/json")
110-
.map_err(|_| ClientError::RequestError)?;
111-
headers
112-
.set("Accept", "application/json")
113-
.map_err(|_| ClientError::RequestError)?;
91+
let request = web_sys::Request::new_with_str_and_init(&self.endpoint, &request_init)
92+
.map_err(|_| ClientError::JsException)?;
11493

115-
for (header_name, header_value) in custom_headers.iter() {
116-
headers
117-
.set(header_name, header_value)
118-
.map_err(|_| ClientError::RequestError)?;
119-
}
94+
let headers = request.headers();
95+
headers
96+
.set("Content-Type", "application/json")
97+
.map_err(|_| ClientError::RequestError)?;
98+
headers
99+
.set("Accept", "application/json")
100+
.map_err(|_| ClientError::RequestError)?;
101+
for (header_name, header_value) in self.headers.iter() {
102+
headers
103+
.set(header_name, header_value)
104+
.map_err(|_| ClientError::RequestError)?;
105+
}
106+
107+
let res = JsFuture::from(window.fetch_with_request(&request))
108+
.await
109+
.map_err(|err| ClientError::Network(js_sys::Error::from(err).message().into()))?;
110+
debug!("response: {:?}", res);
111+
let cast_response = res
112+
.dyn_into::<web_sys::Response>()
113+
.map_err(|_| ClientError::Cast)?;
114+
115+
let text_promise = cast_response
116+
.text()
117+
.map_err(|_| ClientError::ResponseText)?;
118+
let text = JsFuture::from(text_promise)
119+
.await
120+
.map_err(|_| ClientError::ResponseText)?;
120121

121-
Ok((window, request))
122-
})
123-
.and_then(move |(window, request)| {
124-
JsFuture::from(window.fetch_with_request(&request))
125-
.map_err(|err| ClientError::Network(js_sys::Error::from(err).message().into()))
126-
})
127-
.and_then(move |res| {
128-
debug!("response: {:?}", res);
129-
res.dyn_into::<web_sys::Response>()
130-
.map_err(|_| ClientError::Cast)
131-
})
132-
.and_then(move |cast_response| {
133-
cast_response.text().map_err(|_| ClientError::ResponseText)
134-
})
135-
.and_then(move |text_promise| {
136-
JsFuture::from(text_promise).map_err(|_| ClientError::ResponseText)
137-
})
138-
.and_then(|text| {
139-
let response_text = text.as_string().unwrap_or_default();
140-
debug!("response text as string: {:?}", response_text);
141-
serde_json::from_str(&response_text).map_err(|_| ClientError::ResponseShape)
142-
})
122+
let response_text = text.as_string().unwrap_or_default();
123+
debug!("response text as string: {:?}", response_text);
124+
let response_data =
125+
serde_json::from_str(&response_text).map_err(|_| ClientError::ResponseShape)?;
126+
Ok(response_data)
143127
}
144128
}
145129

graphql_client/tests/Germany.graphql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ query Germany {
77
}
88
}
99

10-
query Country($countryCode: String!) {
10+
query Country($countryCode: ID!) {
1111
country(code: $countryCode) {
1212
name
1313
continent {

graphql_client/tests/web.rs

Lines changed: 43 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
#![cfg(target_arch = "wasm32")]
22

3-
use futures::Future;
43
use graphql_client::{web::Client, GraphQLQuery};
5-
use wasm_bindgen::JsValue;
6-
use wasm_bindgen_test::wasm_bindgen_test_configure;
74
use wasm_bindgen_test::*;
85

96
wasm_bindgen_test_configure!(run_in_browser);
@@ -18,30 +15,27 @@ fn build_client() {
1815
#[derive(GraphQLQuery)]
1916
#[graphql(
2017
schema_path = "tests/countries_schema.json",
21-
query_path = "tests/Germany.graphql"
18+
query_path = "tests/Germany.graphql",
19+
response_derives = "Debug"
2220
)]
2321
struct Germany;
2422

25-
#[wasm_bindgen_test(async)]
26-
fn test_germany() -> impl Future<Item = (), Error = JsValue> {
27-
Client::new("https://countries.trevorblades.com/")
23+
#[wasm_bindgen_test]
24+
async fn test_germany() {
25+
let response = Client::new("https://countries.trevorblades.com/")
2826
.call(Germany, germany::Variables)
29-
.map(|response| {
30-
let continent_name = response
31-
.data
32-
.expect("response data is not null")
33-
.country
34-
.expect("country is not null")
35-
.continent
36-
.expect("continent is not null")
37-
.name
38-
.expect("germany is on a continent");
39-
40-
assert_eq!(continent_name, "Europe");
41-
})
42-
.map_err(|err| {
43-
panic!("{:?}", err);
44-
})
27+
.await
28+
.expect("successful response");
29+
let continent_name = response
30+
.data
31+
.expect("response data is not null")
32+
.country
33+
.expect("country is not null")
34+
.continent
35+
.expect("continent is not null")
36+
.name
37+
.expect("germany is on a continent");
38+
assert_eq!(continent_name, "Europe");
4539
}
4640

4741
#[derive(GraphQLQuery)]
@@ -51,50 +45,44 @@ fn test_germany() -> impl Future<Item = (), Error = JsValue> {
5145
)]
5246
struct Country;
5347

54-
#[wasm_bindgen_test(async)]
55-
fn test_country() -> impl Future<Item = (), Error = JsValue> {
56-
Client::new("https://countries.trevorblades.com/")
48+
#[wasm_bindgen_test]
49+
async fn test_country() {
50+
let response = Client::new("https://countries.trevorblades.com/")
5751
.call(
5852
Country,
5953
country::Variables {
6054
country_code: "CN".to_owned(),
6155
},
6256
)
63-
.map(|response| {
64-
let continent_name = response
65-
.data
66-
.expect("response data is not null")
67-
.country
68-
.expect("country is not null")
69-
.continent
70-
.expect("continent is not null")
71-
.name
72-
.expect("country is on a continent");
73-
74-
assert_eq!(continent_name, "Asia");
75-
})
76-
.map_err(|err| {
77-
panic!("{:?}", err);
78-
})
57+
.await
58+
.expect("successful response");
59+
let continent_name = response
60+
.data
61+
.expect("response data is not null")
62+
.country
63+
.expect("country is not null")
64+
.continent
65+
.expect("continent is not null")
66+
.name
67+
.expect("country is on a continent");
68+
assert_eq!(continent_name, "Asia");
7969
}
8070

81-
#[wasm_bindgen_test(async)]
82-
fn test_bad_url() -> impl Future<Item = (), Error = JsValue> {
83-
Client::new("https://example.com/non-existent/graphql/endpoint")
71+
#[wasm_bindgen_test]
72+
async fn test_bad_url() {
73+
let result = Client::new("https://example.com/non-existent/graphql/endpoint")
8474
.call(
8575
Country,
8676
country::Variables {
8777
country_code: "CN".to_owned(),
8878
},
8979
)
90-
.map(|_response| panic!("The API endpoint does not exist, this should not be called."))
91-
.map_err(|err| {
92-
assert_eq!(
93-
err,
94-
graphql_client::web::ClientError::Network(
95-
"NetworkError when attempting to fetch resource.".into()
96-
)
97-
);
98-
})
99-
.then(|_| Ok(()))
80+
.await;
81+
match result {
82+
Ok(_response) => panic!("The API endpoint does not exist, this should not be called."),
83+
Err(graphql_client::web::ClientError::Network(msg)) => {
84+
assert_eq!(msg, "NetworkError when attempting to fetch resource.")
85+
}
86+
Err(err) => panic!("unexpected error: {}", err),
87+
}
10088
}

0 commit comments

Comments
 (0)