JS迭代器及异步

2023-10-16 06:12
文章标签 js 异步 器及 迭代

本文主要是介绍JS迭代器及异步,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 可迭代对象及其相关的迭代器是ES6的一个特性。ES6新增的期约让编写异步代码更容易。关键字async和await是ES2017中引入的,为了简化异步编程提供的新语法,最后,异步迭代器和for/aswait循环是ES2018中引入的,允许在看起来同步的简单循环中操作异步事件流。

1 迭代器与生成器

迭代器3个不同类型:

1)可迭代对象,指的是任何具有专用迭代器方法,且该方法返回迭代器对象的对象。

2)迭代器对象,指的是任何具有next()方法,且该方法返回迭代结果对象的对象。

3)迭代结果对象,具有属性value和done的对象。

可迭代对象的迭代器方法没有使用惯用名称,而是使用了符号Symbol.iterator作为名字。

迭代器本身也是可迭代的。(它们也有Symbol.iterator方法,且返回它们自己。)

1.1 实现可迭代对象

function names() {

    let nameArr = ["Tom","Jerry","Lucy"];
    let current = 0;

    return {
        [Symbol.iterator]() {
            return this;
        },
        next() {
            if (current < nameArr.length) {
                return {value: nameArr[current++],done: false};
            }
            return { done: true };
        },
        return() {
            console.log("迭代器被终止了");
            return {done: true};
        }
    }

}

let iterator = names();
for (let it of iterator) {
    if (it === "Jerry") break;
    console.log(it);
}
// Tom
// 迭代器被终止了

迭代器的return()方法,如果迭代在next()方法done属性为true的结果前停止(常见原因是通过break语句提前退出for/of循环),那么解释器会检查迭代器对象是否有return()方法,如果有,则会调用它。这个return()方法必须返回一个迭代器结果对象,这个对象的属性会被忽略,但返回非对象值会导致报错。

1.2 生成器

语法上类似常规的JS函数,但使用关键字是function*。调用生成器并不会实际执行函数体,而是返回一个生成器对象(是一个迭代器)。调用它的next()方法会导致生成器函数的函数体从头(或从当前位置)开始执行,直至遇见一个yield语句。yield语句的值会成为调用迭代器的next()方法的返回值。

function* numIterator() {
    console.log("numIterator begin");
    yield 1;
    console.log("yield 1 finished");
    yield 2;
    console.log("yield 2 finished");
    yield 3;
    console.log("yield 3 finished");
    console.log("numIterator begin")
}

let iterator = numIterator();
iterator.next(); // numIterator begin
iterator.next(); // yield 1 finished
iterator.next(); // yield 2 finished
iterator.next(); // yield 3 finished numIterator begin
iterator.next(); // 空输出

1.3 高级生成器特性

1)生成器函数的返回值。生成器函数可以有return语句,只是其返回值在迭代的时候会被忽略。但是手工迭代时可通过显示调用next()得到:

function* numIterator() {
    yield 1;
    yield 2;
    return "hello";
}

console.log(...numIterator()); // 1 2
let iterator = numIterator();
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 'hello', done: true }
console.log(iterator.next()); // { value: undefined, done: true }

2)yield表达式的值。yield是一个表达式,可以有值的。调用生成器next()方法时,生成器函数会一直运行直到到达一个yield表达式,yield关键字后面的表达式会被求值,该值成为next()调用的返回值。此时生成器函数在求值yield表达式中途停了下来。下次调用生成器的next()方法时,传给next()的参数会变成暂停的yield表达式的值。

function* numIterator() {
    console.log("begin");
    let y1 = yield 1;
    console.log("y1:",y1);
    let y2 = yield 2;
    console.log("y2:",y2);
}

let iterator = numIterator();
iterator.next("a"); // begin
iterator.next("b"); // y1:b
iterator.next("c"); // y2:c

3)生成器的try/finally。在实现迭代器对象时可定义return()方法,但是在生成器不行,但是生成器可以通过try/ finally来实现同等效果。

function* numIterator() {
    try{
        yield 1;
        yield 2;
        yield 3;
    } finally {
        console.log("迭代")
    }
}

console.log(...numIterator());// 迭代 1 2 3
for (let it of numIterator()) {
    console.log(it);
}
// 迭代
// 1 2 3
// 1
// 2
// 3
// 迭代

2 异步JS

期约是一种为简化异步编程而设计的核心语言特性。

2.1 期约 Promise

       期约是一个对象,表示异步操作的结果。这个结果可能就绪也可能未就绪。

以动词开头来命名返回期约的函数是一种惯例。

function customPro() {
    console.log("异步函数");
    return new Promise((resolve,reject) => {
        resolve("hello 回调函数");
    });
}

function showCallBackInfo(res) {
    console.log("回调1",res);
}

customPro().then(showCallBackInfo);
// 异步函数
// 回调1 hello 回调函数

2.1.1 处理错误

期约有两种处理错误的方式:

1)then()第二个参数传递一个处理错误的函数。

2)catch()方法。

function customPromise(type) {
    console.log("异步函数");
    return  new Promise((resolve,reject) => {
        if (type % 2 === 0) {
            resolve(type % 2);
        } else {
            reject(new Error("不能为基数"));
        }
    });
}

function showCallBackInfo(type) {
    console.log("回调函数:" + type)
}

function catchError(e) {
    console.log(e);
}

customPromise(1).then(showCallBackInfo,catchError); // 异步函数 Error: 不能为基数 (报错)
customPromise(0).then(showCallBackInfo,catchError); // 异步函数 回调函数:0
customPromise(1).then(showCallBackInfo).catch(catchError); // 异步函数 Error: 不能为基数 (报错)

catch(),会捕获期约链上在它位置前面所有期约的错误(如果该期约的错误没被处理的话)。

fun().then(call1).then(call2).catch(errCatch); //catch会捕获fun、call1的错误。

fun().then(call1).catch(errCatch1).then(call2).catch(errCatch2); //errCatch2只会捕获call1的错误,因为fun的错误已被errCatch1捕获并处理(未抛出)。

2.1.2 并行期约

1) Promise.all()接收一个期约对象数组作为输入,返回一个期约。如果输入期约中任意一个拒绝,返回的期约也将拒绝;否则,返回期约会以每个输入期约兑现值的数组兑现。

2)Promise.allSettled()接收一个期约对象数组作为输入,永远不拒绝返回的期约,会等所有输入期约全部落定后兑现。其返回的期约解决为一个对象数组,其中每个对象都应对应一个输入期约,且都有一个status属性,值为fulfilled或rejected,如果status属性值为fulfilled,值该对象还有个value属性,包含兑现的值。如果status为rejected,那该对象还有个reason属性。

3)Promise.race(),接收一个期约对象数组作为输入,返回一个期约,这个期约会在输入数组中的期约有一个兑现或拒绝时马上兑现或拒绝。

2.1.3 创建期约

1)从头开始创建期约。

function customPromise(type) {
    console.log("自定义异步函数");
    // 创建新期约
    return new Promise((resolve,reject) => {
        if (type < 0) reject(new Error("不能小于0"));
        else resolve("你好啊");
    });
}

function showCallBackInfo(info) {
    console.log(info);
}

function dealErr(error) {
    console.log(error.message);
}
customPromise(2).then(showCallBackInfo).catch(dealErr);
customPromise(-1).then(showCallBackInfo).catch(dealErr);
// 自定义异步函数
// 自定义异步函数
// 你好啊
// 不能小于0

2)基于其他期约的期约。

function customPromise() {
    return new Promise((resolve) => {
        resolve();
    })
}

function customPromise2() {
    return customPromise().then(_ => "hello");
}

customPromise2().then(res => {
    console.log("res:",res); //res:hello
})

3)基于同步值的期约。

Promise.resolve() 接收一个值作为参数,并会立即(异步)以该值兑现一个期约。Promise.reject()则返回以该参数作为理由而拒绝的期约。

Promise.resolve("hello").then(res => {
    console.log("res:",res); // res: hello
})

2.2 async 和 await

ES2017 新增了async和await两个关键字。

function sleep(time) {
    return new Promise(resolve => setTimeout(resolve,time * 1000))
}

async function countDown() {
    let begin = new Date();
    console.log("开始");
    await sleep(1);
    await sleep(2);
    await sleep(2);
    let end = new Date();
    console.log("结束");
    return end.getTime() - begin.getTime();
}

countDown().then(time => {
    console.log("耗时:" + time / 1000 + "s");
});
// 开始
// 结束
// 耗时:5.009s

实现细节,编译器将async函数包装成一个返回期约的函数。

这篇关于JS迭代器及异步的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/219599

相关文章

JS常用组件收集

收集了一些平时遇到的前端比较优秀的组件,方便以后开发的时候查找!!! 函数工具: Lodash 页面固定: stickUp、jQuery.Pin 轮播: unslider、swiper 开关: switch 复选框: icheck 气泡: grumble 隐藏元素: Headroom

在JS中的设计模式的单例模式、策略模式、代理模式、原型模式浅讲

1. 单例模式(Singleton Pattern) 确保一个类只有一个实例,并提供一个全局访问点。 示例代码: class Singleton {constructor() {if (Singleton.instance) {return Singleton.instance;}Singleton.instance = this;this.data = [];}addData(value)

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件

EasyPlayer.js网页H5 Web js播放器能力合集

最近遇到一个需求,要求做一款播放器,发现能力上跟EasyPlayer.js基本一致,满足要求: 需求 功性能 分类 需求描述 功能 预览 分屏模式 单分屏(单屏/全屏) 多分屏(2*2) 多分屏(3*3) 多分屏(4*4) 播放控制 播放(单个或全部) 暂停(暂停时展示最后一帧画面) 停止(单个或全部) 声音控制(开关/音量调节) 主辅码流切换 辅助功能 屏

迭代器模式iterator

学习笔记,原文链接 https://refactoringguru.cn/design-patterns/iterator 不暴露集合底层表现形式 (列表、 栈和树等) 的情况下遍历集合中所有的元素

使用JS/Jquery获得父窗口的几个方法(笔记)

<pre name="code" class="javascript">取父窗口的元素方法:$(selector, window.parent.document);那么你取父窗口的父窗口的元素就可以用:$(selector, window.parent.parent.document);如题: $(selector, window.top.document);//获得顶级窗口里面的元素 $(

js异步提交form表单的解决方案

1.定义异步提交表单的方法 (通用方法) /*** 异步提交form表单* @param options {form:form表单元素,success:执行成功后处理函数}* <span style="color:#ff0000;"><strong>@注意 后台接收参数要解码否则中文会导致乱码 如:URLDecoder.decode(param,"UTF-8")</strong></span>

js react 笔记 2

起因, 目的: 记录一些 js, react, css 1. 生成一个随机的 uuid // 需要先安装 crypto 模块const { randomUUID } = require('crypto');const uuid = randomUUID();console.log(uuid); // 输出类似 '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'

学习记录:js算法(二十八):删除排序链表中的重复元素、删除排序链表中的重复元素II

文章目录 删除排序链表中的重复元素我的思路解法一:循环解法二:递归 网上思路 删除排序链表中的重复元素 II我的思路网上思路 总结 删除排序链表中的重复元素 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 图一 图二 示例 1:(图一)输入:head = [1,1,2]输出:[1,2]示例 2:(图

uuid.js 使用

相关代码 import { NIL } from "uuid";/** 验证UUID* 为空 则返回 false* @param uuid* @returns {boolean}*/export function MyUUIDValidate(uuid: any): boolean {if (typeof uuid === "string" && uuid !== NIL) { //uuid