遍历 JavaScript 值
返回 js_sys::Iterator
的方法
一些 JavaScript 集合具有用于遍历其值或键的方法
Map::values
Set::keys
- 等等...
这些方法返回 js_sys::Iterator
,它是 JavaScript 对象的 Rust 表示,该对象具有一个 next
方法,该方法要么返回迭代中的下一个项目,要么表示迭代已完成,要么抛出错误。也就是说,js_sys::Iterator
代表一个实现了 鸭子类型 JavaScript 迭代协议 的对象。
js_sys::Iterator
可以通过引用(转换为 js_sys::Iter<'a>
)或通过值(转换为 js_sys::IntoIter
)转换为 Rust 迭代器。Rust 迭代器将产生类型为 Result<JsValue>
的项目。如果它产生 Ok(...)
,则 JS 迭代器协议返回了一个元素。如果它产生 Err(...)
,则 JS 迭代器协议抛出了一个异常。
#![allow(unused)] fn main() { 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 } }
遍历任何实现迭代器协议的 JavaScript 对象
您可以手动测试一个对象是否实现了 JS 的鸭子类型迭代器协议,如果实现了,则将其转换为 js_sys::Iterator
,然后您可以最终遍历它。但是,您不需要手动执行此操作,因为我们已将其捆绑为 js_sys::try_iter
函数!
例如,我们可以编写一个函数,该函数从任何 JS 可迭代对象中收集数字,并将它们作为 Array
返回
#![allow(unused)] fn main() { 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 = js_sys::try_iter(some_iterable)?.ok_or_else(|| { "need to pass iterable JS values!" })?; 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.as_f64().is_some() { nums.push(&x); } } Ok(nums) } }