ES6+ (中)

本文详细介绍了ES6中的迭代器机制,包括可迭代对象、工作原理和使用示例。接着,深入探讨了生成器的创建、调用、yield表达式的用法以及在异步编程中的应用。接着,讲解了Promise的基本用法、链式操作、Promise.all和Promise.race。最后,阐述了async/await如何简化异步代码,以及它们在解决回调地狱中的作用。
摘要由CSDN通过智能技术生成

ES6+ (中)

一、迭代器

  • 所谓迭代就是逐个访问数据中各个成员的过程,在ES6中凡是能使用**for…of…**语句的对象,都叫做可迭代对象

  • 迭代器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作

  • 原生具备 iterator 接口的数据类型(可用 for of 遍历):

    • Array
    • Arguments
    • Set
    • Map
    • String
    • NodeList
    • 需要注意的是Object不具备 iterator 接口
  • 工作原理:

    1. 创建一个指针对象,指向当前数据结构的起始位置;

    2. 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员;

    3. 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员;

    4. 每调用 next 方法返回一个包含 value 和 done 属性的对象;

      let arr = ['张三','李四','王五'];
      let iterator = arr[Symbol.iterator]();
      
      let result = iterator.next();
      while(!result.done){
          console.log(result.value);
          result = iterator.next()
      }
      

二、生成器

  • 生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
2.1 创建生成器
  • 生成器是一种返回迭代器的函数,通过function关键字后的星号( * )来表示

    // *左右有没有空格都可以
    function * generator(){
        console.log('Hello generator!')
    }
    
    // 返回的是一个迭代器对象
    console.log(generator())
    

在这里插入图片描述

2.2 调用生成器
  • 调用生成器函数只会返回一个迭代器对象,所以还需要执行迭代器的next()方法才能执行生器中的代码

    // 创建生成器
    function * generator(){
        console.log('Hello generator!')
    }
    
    // 返回迭代器
    let iterator = generator();
    
    // 执行迭代器的next()方法
    iterator.next();
    
2.3 yield
  • yield的使用和return的使用没什么区别,只是yield会返回一个生成器

  • yield可以将生成器的代码分隔起多个部分,然后通过执行next()方法依次执行

    function * generator(){
        console.log('part one');
        yield 1;
        console.log('part two');
        yield 2;
        console.log('part three');
        yield 3;
        console.log('part four');
    }
    
    var iterator = generator();
    console.log( iterator.next() ); // { done : false, value : 1 }
    console.log( iterator.next() ); // { done : false, value : 2 }
    console.log( iterator.next() ); // { done : false, value : 3 }
    console.log( iterator.next() ); // { done : true, value : undefined }
    
  • 生成器返回的是迭代器对象,当然也可以通过for…of进行遍历,遍历的出来的结果为yield的值

    // 创建生成器
    function * generator(){
        let num = 100;
        yield num;
        num++;
        yield num;   
        num++;
        yield num;
    }
    
    // 返回迭代器
    let iterator = generator();
    
    // 遍历迭代器
    for( v of iterator){
        console.log(v);
    }
    
2.4 生成器异步编程应用
  • 常见异步操作:

    • 文件操作 : fs 文件读写
    • 网络操作: ajax
    • 数据库操作
    • 定时器操作
    • 事件操作
  • 回调地狱问题:

    • 有多个异步任务,每个任务执行时间是随机的?

      setTimeout(function(){
          console.log('任务一');
      },Math.random() * 1000)
      
      setTimeout(function(){
          console.log('任务二');
      },Math.random() * 1000)
      
      
      setTimeout(function(){
          console.log('任务三');
      },Math.random() * 1000)
      
    • 如何让这些异步任务,依次执行?普遍采用的方式就是回调嵌套,但如果嵌套的层次过多就会出现回调地狱的现象,代码看起来十分混乱,可读性极差。

      setTimeout(function(){
          console.log('任务一');
          setTimeout(function(){
              console.log('任务二');
              setTimeout(function(){
                  console.log('任务三')
              },Math.random() * 1000)
          },Math.random() * 1000)
      },Math.random() * 1000)
      
    • 生成器可以解决回调地狱的问题

      function task1(){
          setTimeout(function(){
              console.log('任务一');
              taskIterator.next();
          },Math.random() * 1000)
          
      }
      
      function task2(){
          setTimeout(function(){
              console.log('任务二');
              taskIterator.next();
          },Math.random() * 1000)
         
      }
      
      function task3(){
          setTimeout(function(){
              console.log('任务三');
          },Math.random() * 1000)
      }
      
      
      function * mytasks(){    
          yield task1();
          yield task2();
          yield task3();
      } 
      
      let taskIterator = mytasks();
      taskIterator.next();
      
    • 生成器参数传递问题

      function task1(){
          setTimeout(function(){
              console.log('任务一');
              taskIterator.next('结果1');
          },Math.random() * 1000)
          
      }
      
      function task2(data){
          console.log(data);
          setTimeout(function(){
              console.log('任务二');
              taskIterator.next('结果2');
          },Math.random() * 1000)
      }
      
      function task3(data){
          console.log(data);
          setTimeout(function(){
              console.log('任务三');
              taskIterator.next('结果3');
          },Math.random() * 1000)
      }
      
      
      function * mytasks(){    
         let a = yield task1();
         let b = yield task2(a);
         let c = yield task3(b);
         console.log(c);
      } 
      
      let taskIterator = mytasks();
      taskIterator.next();
      

三、Promise

Promise是ES6引入的异步编程的新的解决方案。

语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果

promise有三种状态:

  • pending (进行中)
  • resolve (成功)
  • reject (失败)
3.1 基本用法
// 定义promise
const p = new Promise((resolve,reject){
    // 异步操作 .......              
  	if(成功){
    	resolve('成功结果');
	}else{
        reject('失败原因');
    }                    
})


// 执行promise (方式一)
p.then(
    data => {
    	// 获取成功结果
	},
    error => {
    	// 获取失败原因
	}
)

// 执行promise (方式二)
p.then(data => {
    // 获取成功结果
}).catch(error => {
    // 获取失败原因
})


demo:

// 定义promise
const p = new Promise((resolve,reject) => {
    // 异步操作 .......  
    setTimeout(function(){
        let result = false;
        if(result){
    	    resolve('成功结果');
        }else{
            reject('失败原因');
        }   
    })                             
})

// 执行promise方式一
p.then(
    data => {
        console.log(data);
    },
    error => {
        console.log(error);
    }
)

// 执行promise方式二(推荐)
p.then(data => {
    console.log(data);
}).catch(error => {
    console.log(error);
})
3.2 链式操作
  • then方法的返回结果是Promise对象,对象状态由回调函数的执行结果来决定

  • 所以then方法是可以被链式调用的,利用这一特性可以解决异步编程的回调地狱问题

    const p = new Promise((resolve,reject) => {
        setTimeout(function(){
            console.log('任务一');
            resolve('结果1')
        },Math.random() * 1000)
    })
    
    p.then(data=>{
        console.log(data);
        return new Promise((resolve,reject)=>{
            setTimeout(function(){
                console.log('任务二');
                resolve('结果2')
            },Math.random() * 1000)
        })
       
    }).then(data => {
        console.log(data);
        setTimeout(function(){
            console.log('任务三');
            console.log('结果3')
        },Math.random() * 1000)
    })
    
3.3 Promise.all([p1,p2,p3])
  • Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。

  • 所有异步完成才会输出结果

  • 只要有一个reject则会执行回调失败

  • 需要特别注意的是,Promise.all获得的成功结果的数组里面的数据顺序和Promise.all接收到的数组顺序是一致的

    const p1 =  new  Promise((resolve,reject) =>{
            setTimeout(function(){
                console.log('任务一'); 
                resolve('结果1')
            },Math.random() * 1000)
        }) 
    
    const p2=  new  Promise((resolve,reject) =>{
            setTimeout(function(){
                console.log('任务二'); 
                resolve('结果2')
            },Math.random() * 1000)
        }) 
    
    
    
    const p3 =  new  Promise((resolve,reject) =>{
            setTimeout(function(){
                console.log('任务二'); 
                resolve('结果3')
            },Math.random() * 1000)
    }) 
    
    
    
    let p = Promise.all([p1,p2,p3]);
    
    p.then(data=>{
        console.log(data);
    }).catch(error=>{
        console.log(error)
    })
    
3.4 Promise.race([p1,p2,p3])
  • 顾名思义,Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态

    
    const p1 =  new  Promise((resolve,reject) =>{
            setTimeout(function(){
                console.log('任务一'); 
                resolve('结果1')
            },Math.random() * 1000)
        }) 
    
    
    
    
    const p2=  new  Promise((resolve,reject) =>{
            setTimeout(function(){
                console.log('任务二'); 
                resolve('结果2')
            },Math.random() * 1000)
        }) 
    
    
    
    const p3 =  new  Promise((resolve,reject) =>{
            setTimeout(function(){
                console.log('任务二'); 
                resolve('结果3')
            },Math.random() * 1000)
    }) 
    
    
    
    let p = Promise.race([p1,p2,p3]);
    
    p.then(data=>{
        console.log(data);
    }).catch(error=>{
        console.log(error)
    })
    

四、async/await

async是对promise的一种扩展

async和await两种语法结合可以让异步代码像同步代码一样依次执行

4.1 async函数
  • async修饰的函数的返回值为promise对象

  • promise对象的结果由async函数的返回值决定

    async function fun(){
        return 'Hello';
        // throw new Error('出错了')
        
        //return new Promise((resolve,reject) => {
            //resolve('成功')
            // reject('失败')
        //})
      
    }
    
    //console.log(fun());
    const p = fun();
    
    p.then(data => {
        console.log(data)
    }).catch(error => {
        console.warn(error)
    })
    
4.2 await表达式
  • await 关键字只能用在async 函数中

  • await右侧的表达式一般为promise对象

  • await返回的是promise成功的值

  • await的promise失败了,就会抛出异常,需要通过try…catch…进行异常处理

    // 定义promise
    const p = new Promise((resolve,reject) => {
        resolve('成功');
        // reject('失败')
    })
    
    // 定义async函数
    async function fun(){
        try{
            let data = await p;
            console.log(data);
        }catch(error){
            console.log(error);
        }
    }
    
    
    // 调用函数
    fun();
    
4.3 解决回调地狱

 // 异步任务1
 function task1(){
     return new  Promise((resolve,reject) =>{
         setTimeout(function(){
             console.log('任务一'); 
             resolve('结果1')
         },Math.random() * 1000)
     }) 
 }
 
 // 异步任务2
 function task2(data){
     console.log(data);
     return new Promise((resolve,reject) =>{
         setTimeout(function(){
             console.log('任务二'); 
             resolve('结果2')
         },Math.random() * 1000)
     }) 
 }
 // 异步任务3
 function task3(data){
     console.log(data);
     return new  Promise((resolve,reject) =>{
         setTimeout(function(){
             console.log('任务三'); 
             resolve('结果3')
         },Math.random() * 1000)
     }) 
 }
 
 // async函数
 async function fun(){
     let result1 = await task1();
     let result2 = await task2(result1);
     let result3 = await task3(result2);
     console.log(result3);
 }
 
 // 执行async函数
 fun();

og(‘任务二’);
resolve(‘结果2’)
},Math.random() * 1000)
})
}
// 异步任务3
function task3(data){
console.log(data);
return new Promise((resolve,reject) =>{
setTimeout(function(){
console.log(‘任务三’);
resolve(‘结果3’)
},Math.random() * 1000)
})
}

// async函数
async function fun(){
let result1 = await task1();
let result2 = await task2(result1);
let result3 = await task3(result2);
console.log(result3);
}

// 执行async函数
fun();




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值