Merge pull request #729 from eminence/fetch

Initial example for the Fetch API
This commit is contained in:
Alex Crichton 2018-08-20 10:35:57 -07:00 committed by GitHub
commit adcc0dd23e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 178 additions and 20 deletions

View File

@ -57,6 +57,7 @@ members = [
"examples/comments",
"examples/console_log",
"examples/dom",
"examples/fetch",
"examples/guide-supported-types-examples",
"examples/hello_world",
"examples/import_js",

View File

@ -10,31 +10,33 @@ when using `build.sh`!
The examples here are:
* `hello_world` - the "hello world" of `#[wasm_bindgen]`, aka throwing up a
dialog greeting you
* `console_log` - a showcase of `#[wasm_bindgen]` importing classes and how to
bind `console.log`
* `math` - like `console_log` except showing how to import Math-related
functions instead
* `dom` - an example of accessing the global `document` object and appending
HTML to it
* `smorgasboard` - a bunch of features all thrown into one, showing off the
various capabilities of the `#[wasm_bindgen]` macro and what you can do with
it from JS
* `performance` - how to import APIs like `performance.now()` and time various
operations in Rust
* `wasm-in-wasm` - how to interact with namespaced APIs like
`WebAssembly.Module` and shows off creation of a WebAssembly module from Rust
* `closures` - an example of how to invoke functions like `setInterval` or use
the `onclick` property in conjunction with closures.
* `no_modules` - an example of how to use the `--no-modules` flag to
the `wasm-bindgen` CLI tool
* `add` - an example of generating a tiny wasm binary, one that only adds two
numbers.
* `asm.js` - an example of using the `wasm2asm` tool from [binaryen] to convert
the generated WebAssembly to normal JS
* `char` - an example of passing the rust `char` type to and from the js `string` type
* `import_js` - an example of importing local JS functionality into a crate
* `closures` - an example of how to invoke functions like `setInterval` or use
the `onclick` property in conjunction with closures.
* `comments` - an example of how Rust comments are copied into js bindings
* `console_log` - a showcase of `#[wasm_bindgen]` importing classes and how to
bind `console.log`
* `dom` - an example of accessing the global `document` object and appending
HTML to it
* `fetch` -- how to use the Fetch API to make async http requests
* `hello_world` - the "hello world" of `#[wasm_bindgen]`, aka throwing up a
dialog greeting you
* `import_js` - an example of importing local JS functionality into a crate
* `math` - like `console_log` except showing how to import Math-related
functions instead
* `no_modules` - an example of how to use the `--no-modules` flag to
the `wasm-bindgen` CLI tool
* `performance` - how to import APIs like `performance.now()` and time various
operations in Rust
* `smorgasboard` - a bunch of features all thrown into one, showing off the
various capabilities of the `#[wasm_bindgen]` macro and what you can do with
it from JS
* `wasm-in-wasm` - how to interact with namespaced APIs like
`WebAssembly.Module` and shows off creation of a WebAssembly module from Rust
* `webaudio` - how to use the Web Audio APIs to generate sounds
[binaryen]: https://github.com/WebAssembly/binaryen

4
examples/fetch/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
fetch.d.ts
fetch.js
fetch_bg.wasm
package-lock.json

16
examples/fetch/Cargo.toml Normal file
View File

@ -0,0 +1,16 @@
[package]
name = "fetch"
version = "0.1.0"
authors = ["Andrew Chin <achin@eminence32.net>"]
[lib]
crate-type = ["cdylib"]
[dependencies]
futures = "0.1.20"
wasm-bindgen = { path = "../..", features = ["serde-serialize"] }
js-sys = { path = "../../crates/js-sys" }
web-sys = { path = "../../crates/web-sys" }
wasm-bindgen-futures = { path = "../../crates/futures" }
serde = "^1.0.59"
serde_derive = "^1.0.59"

2
examples/fetch/build.bat Normal file
View File

@ -0,0 +1,2 @@
cargo +nightly build --target wasm32-unknown-unknown
cargo +nightly run --manifest-path ../../crates/cli/Cargo.toml --bin wasm-bindgen -- ../../target/wasm32-unknown-unknown/debug/fetch.wasm --out-dir .

10
examples/fetch/build.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh
# For more coments about what's going on here, see the `hello_world` example
set -ex
cargo +nightly build --target wasm32-unknown-unknown
cargo +nightly run --manifest-path ../../crates/cli/Cargo.toml \
--bin wasm-bindgen -- \
../../target/wasm32-unknown-unknown/debug/fetch.wasm --out-dir .

10
examples/fetch/index.html Normal file
View File

@ -0,0 +1,10 @@
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type"/>
</head>
<body>
<script src='./index.js'></script>
</body>
</html>

11
examples/fetch/index.js Normal file
View File

@ -0,0 +1,11 @@
const rust = import('./fetch');
rust.then(m => {
m.run().then((data) => {
console.log(data);
console.log("The latest commit to the wasm-bindgen %s branch is:", data.name);
console.log("%s, authored by %s <%s>", data.commit.sha, data.commit.commit.author.name, data.commit.commit.author.email);
})
});

View File

@ -0,0 +1,9 @@
{
"scripts": {
"serve": "webpack-serve ./webpack.config.js"
},
"devDependencies": {
"webpack": "^4.16.5",
"webpack-serve": "^2.0.2"
}
}

83
examples/fetch/src/lib.rs Normal file
View File

@ -0,0 +1,83 @@
extern crate wasm_bindgen;
extern crate js_sys;
extern crate web_sys;
extern crate wasm_bindgen_futures;
extern crate futures;
#[macro_use]
extern crate serde_derive;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use js_sys::Promise;
use web_sys::{Request, RequestInit, RequestMode, Response, Window};
use wasm_bindgen_futures::JsFuture;
use futures::{future, Future};
use wasm_bindgen_futures::future_to_promise;
// A struct to hold some data from the github Branch API.
// Note how we don't have to define every member -- serde will ignore extra data when deserializing
#[derive(Debug, Serialize, Deserialize)]
pub struct Branch {
pub name: String,
pub commit: Commit,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Commit {
pub sha: String,
pub commit: CommitDetails,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct CommitDetails {
pub author: Signature,
pub committer: Signature,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Signature {
pub name: String,
pub email: String,
}
#[wasm_bindgen]
extern "C" {
static window: Window;
}
#[wasm_bindgen]
pub fn run() -> Promise {
let mut request_options = RequestInit::new();
request_options.method("GET");
request_options.mode(RequestMode::Cors);
let req = Request::new_using_usv_str_and_request_init("https://api.github.com/repos/rustwasm/wasm-bindgen/branches/master", &request_options).unwrap();
// the RequestInit struct will eventually support setting headers, but that's missing right now
req.headers().set("Accept", "application/vnd.github.v3+json").unwrap();
let req_promise = window.fetch_using_request(&req);
let to_return = JsFuture::from(req_promise).and_then(|resp_value| {
// resp_value is a Response object
assert!(resp_value.is_instance_of::<Response>());
let resp: Response = resp_value.dyn_into().unwrap();
resp.json()
}).and_then(|json_value: Promise| {
// convert this other promise into a rust Future
JsFuture::from(json_value)
}).and_then(|json| {
// Use serde to parse this into a struct
let branch_info: Branch = json.into_serde().unwrap();
// Send the Branch struct back to javascript as an object
future::ok(JsValue::from_serde(&branch_info).unwrap())
});
// Convert this rust future back into a javascript promise.
// Return it to javascript so that it can be driven to completion.
future_to_promise(to_return)
}

View File

@ -0,0 +1,10 @@
const path = require('path');
module.exports = {
entry: './index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.js',
},
mode: 'development'
};