mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-03-16 02:00:51 +00:00
guide: Add section about iterating over JS values
This commit is contained in:
parent
7db28b4548
commit
dfd0f534f9
@ -30,6 +30,7 @@
|
||||
- [Passing Rust Closures to JS](./reference/passing-rust-closures-to-js.md)
|
||||
- [Receiving JS Closures in Rust](./reference/receiving-js-closures-in-rust.md)
|
||||
- [`Promise`s and `Future`s](./reference/js-promises-and-rust-futures.md)
|
||||
- [Iterating over JS Values](./reference/iterating-over-js-values.md)
|
||||
- [No ES Modules](./reference/no-esm.md)
|
||||
- [Arbitrary Data with Serde](./reference/arbitrary-data-with-serde.md)
|
||||
- [Accessing Properties of Untyped JS Values](./reference/accessing-properties-of-untyped-js-values.md)
|
||||
|
95
guide/src/reference/iterating-over-js-values.md
Normal file
95
guide/src/reference/iterating-over-js-values.md
Normal file
@ -0,0 +1,95 @@
|
||||
# Iterating over JavaScript Values
|
||||
|
||||
## Methods That Return `js_sys::Iterator`
|
||||
|
||||
Some JavaScript collections have methods for iterating over their values or
|
||||
keys:
|
||||
|
||||
* [`Map::values`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Map.html#method.values)
|
||||
* [`Set::keys`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Set.html#method.keys)
|
||||
* etc...
|
||||
|
||||
These methods return
|
||||
[`js_sys::Iterator`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Iterator.html),
|
||||
which is the Rust representation of a JavaScript object that has a `next` method
|
||||
that either returns the next item in the iteration, notes that iteration has
|
||||
completed, or throws an error. That is, `js_sys::Iterator` represents an object
|
||||
that implements [the duck-typed JavaScript iteration
|
||||
protocol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols).
|
||||
|
||||
`js_sys::Iterator` can be converted into a Rust iterator either by reference
|
||||
(into
|
||||
[`js_sys::Iter<'a>`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.Iter.html))
|
||||
or by value (into
|
||||
[`js_sys::IntoIter`](https://rustwasm.github.io/wasm-bindgen/api/js_sys/struct.IntoIter.html)). The
|
||||
Rust iterator will yield items of type `Result<JsValue>`. If it yields an
|
||||
`Ok(...)`, then the JS iterator protocol returned an element. If it yields an
|
||||
`Err(...)`, then the JS iterator protocol threw an exception.
|
||||
|
||||
```rust
|
||||
extern crate js_sys;
|
||||
extern crate wasm_bindgen;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn count_strings_in_set(set: &js_sys::Set) -> u32 {
|
||||
let mut count = 0;
|
||||
|
||||
// Call `keys` to get an iterator over the set's elements. Because this is
|
||||
// in a `for ... in ...` loop, Rust will automatically call its
|
||||
// `IntoIterator` trait implementation to convert it into a Rust iterator.
|
||||
for x in set.keys() {
|
||||
// We know the built-in iterator for set elements won't throw
|
||||
// exceptions, so just unwrap the element. If this was an untrusted
|
||||
// iterator, we might want to explicitly handle the case where it throws
|
||||
// an exception instead of returning a `{ value, done }` object.
|
||||
let x = x.unwrap();
|
||||
|
||||
// If `x` is a string, increment our count of strings in the set!
|
||||
if x.is_string() {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
count
|
||||
}
|
||||
```
|
||||
|
||||
## Iterating Over <u>Any</u> JavaScript Object that Implements the Iterator Protocol
|
||||
|
||||
You could manually test for whether an object implements JS's duck-typed
|
||||
iterator protocol, and if so, convert it into a `js_sys::Iterator` that you can
|
||||
finally iterate over. You don't need to do this by-hand, however, since we
|
||||
bundled this up as [the `js_sys::try_iter`
|
||||
function!](https://rustwasm.github.io/wasm-bindgen/api/js_sys/fn.try_iter.html)
|
||||
|
||||
For example, we can write a function that collects the numbers from any JS
|
||||
iterable and returns them as an `Array`:
|
||||
|
||||
```rust
|
||||
extern crate js_sys;
|
||||
extern crate wasm_bindgen;
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn collect_numbers(some_iterable: &JsValue) -> Result<js_sys::Array, JsValue> {
|
||||
let nums = js_sys::Array::new();
|
||||
|
||||
let iterator = match js_sys::try_iter(some_iterable)?.ok_or_else(|| {
|
||||
"need to pass iterable JS values!".into()
|
||||
})?;
|
||||
|
||||
for x in iterator {
|
||||
// If the iterator's `next` method throws an error, propagate it
|
||||
// up to the caller.
|
||||
let x = x?;
|
||||
|
||||
// If `x` is a number, add it to our array of numbers!
|
||||
if x.is_f64() {
|
||||
nums.push(&x);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(nums)
|
||||
}
|
||||
```
|
Loading…
x
Reference in New Issue
Block a user