ES6—异步解决方案

1 Promise对象

1.1 定义

      promise是一种异步编程解决方案,Promise是一个容器,保存着将来才会执行的代码;从语法角度来说Promise是一个对象,可以用来获取异步操作的消息。
      异步操作,同步解决,避免了层层嵌套的回调函数。

1.2 特点

    Promise 对象代表一个异步操作,有三种状态:
        pending(进行中)、fulfilled(已成功)、rejected(已失败)
    状态不受外界影响,只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
    Promise 对象的状态改变,只有两种可能:从pending变为fulfilled从pending变为rejected。只要这两种情况发生,状态就凝固不会再变了,会一直保持这个结果,最后就返回 resolved(已定型)结果。

1.2 实例化和实例方法

(1) 实例化
    Promise 构造函数接收一个函数作为参数,也就是回调函数;该函数有两个参数,分别是resolve和reject。resolve作为成功的回调函数,reject作为失败的回调函数。
(2) 实例方法:
    定义在 Promise.prototype 中的方法,通过 Promise 的实例可以直接调用。

  1. .then() 状态由pending=>fulfilled的时候(异步操作成功之后)执行该回调函数
    参数: 回调函数,回调函数的参数为resolve函数传递过来的值
    返回值: 返回一个新的Promise实例对象,因此可以使用链式调用
  2. .catch() 状态由pending=>rejected的时候(异步操作失败之后)执行该回调函数
    参数: 回调函数,回调函数的参数为reject函数传递过来的值
    返回值: 返回一个新的Promise实例对象,因此可以使用链式调用
  3. .finally() 无论异步操作执行成功失败与否,都会执行该回调
    参数: 回调函数(回调函数没有参数)
    返回值: 返回一个新的Promise实例对象
// 1.创建promise对象
	let p1=new Promise(function(resolve,reject){
		//非异步  假设异步操作执行成功,修改promise对象状态为成功状态
	    if(1>0){
	        resolve("成功");
	    }else{
	        reject("失败");
	    }
	})
	//在promise原型里有then和catch
        // 1.then方法表示的是成功之后的回调,对应resolve
        // 2.catch方法表示的是失败之后的回调,对应reject
	p1.then((res)=>{
	    console.log(res);
	}).catch((err)=>{
	    console.log(err);
	})
	//成功
	let p2=new Promise((resolve,reject)=>{
	    setTimeout(()=>{
	        let data='用户的数据';
	        resolve(data); //调用resolve之后,对象状态变为成功
	        // reject('数据读取失败');
	    },1000);
	})
	//then()如果有两个参数,第一个参数表示成功的回调,第二个表示失败的回调
	//分别代表resolve()和reject()
	p2.then((res)=>{
	    console.log(res,'成功');
	},(err)=>{
	    console.log(err,'失败');
	})

promise 是一个构造函数,下面来简单手写一个 promise:

let promise = new Promise((resolve,reject)=>{
       if(res){
          resolve(res);
       }else{
          reject(err);
       }
    })
    promise.then((res)=>{
        console.log(res);
     }).catch((err)=>{
        console.log(err)
     })

(3) 静态方法
    定义在Promise中的方法,通过Promise可以直接调用。
promise静态方法

//考虑到可能有多个请求需要发送,需要创建多个承诺对象,所以采用工厂函数进行封装
 function getPromise(url,method='get',data=null){
    return new Promise((resolve,reject)=>{
        $.ajax({
            url:url,
            method:method,
            data:data,
            success(res){
                resolve(res)
            },
            error(err){
                reject(err)
            }
        })
    })
 }
 let p1=getPromise('url');
 let p2=getPromise('url');
  // p1.then((res)=>{
  //     console.log(res,'1111111')
  // })
  // p2.then((res)=>{
  //     console.log(res,'222222')
  // })
  // all 只有两个异步操作请求都成功才会返回成功的结果,否则返回失败对象
  // race 谁的响应先拿到用谁的结果 无论成功与否
  //any 有成功用成功的,都失败就失败
  let p=Promise.any([p1,p2]);
  p.then((res)=>{
      console.log(res)
  }).catch((err)=>{
      console.log(err)
  })

2 迭代器

2.1 定义

      迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制,任何数据结构只要部署Iterator接口(对象中的一个属性),就可以完成遍历操作。
原生具备iterator接口的数据(可用for of遍历):
      Array , Arguments , Set , Map , String , TypedArray , NodeList

2.2 Iterator的作用:

     1)为各种数据结构,提供一个统一的、简便的访问接口
     2)使得数据结构的成员能够按某种次序排列
     3)ES6创造了一种新的遍历命令for…of循环,Iterator接口主要供for…of消费

2.3 遍历过程:

     1)创建一个指针对象,指向当前数据结构的起始位置。遍历器对象本质上就是一个指针对象。
     2) 第一次调用指针对象的next()方法,可以将指针指向数据结构的第一个成员。
     3)接下来不断调用next()方法,指针一直往后移动,直到指向最后一个成员
     4)每调用next()方法返回一个包含value和done属性的对象

let arr1=['tom','vicky','jacky'];
	let values=arr1.values();
	console.log(values.next());	 //{ value: 'tom', done: false }
	console.log(values.next()); //{ value: 'vicky', done: false }
	console.log(values.next()); //{ value: 'jacky', done: false }
	console.log(values.next()); //{ value: undefined, done: true }
	//done属性是一个布尔值,表示是否遍历结束,false表示还没有结束,true表示结束

3 Generator 函数

3.1 简介

     Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同;简单的把Generator 理解为一个状态机,封装了多个内部状态。执行Generator 函数会返回一个迭代器对象,可以通过调用迭代器next依次遍历Generator函数内部的每一个状态。

3.2 特征

     1)function关键字与函数名之间有个星号
     2)函数内部使用yield表达式

//1.创建Generator函数  每个状态之间都是独立的,运行都是互不干扰的
	function* myGenFun(){
		console.log('状态一');
	    yield 'hello';
	    console.log('状态二');
	    yield 'world';
	    console.log('状态三');
	    return 'ending'; //return标志该函数的结束
	}
	let result=myGenFun();
	console.log(result);//返回的是一个Generator对象,也是一个迭代器对象
	console.log(result.next());
	console.log(result.next());
	console.log(result.next());
	//打印结果:
	//Object [Generator] {}
	//状态一
	//{ value: 'hello', done: false }
	//状态二
	//{ value: 'world', done: false }
	//状态三
	//{ value: 'ending', done: true }

上面的代码有三个状态:‘hello’ ‘world’ ‘ending’
       Generator 函数的调用方法与普通函数一样,也是在函数名后面加上一对圆括号。不同的是,调用 Generator 函数后,该函数并不执行,返回的也不是函数运行结果,而是一个迭代器对象,调用遍历器对象的next方法,使得指针移向下一个状态。
       每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。也就是说,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行。

上面的代码一共调用了四次next方法:
      next()第一次调用:Generator 函数开始执行,直到遇到第一个yield表达式为止。next方法返回一个对象,它的value属性就是当前yield表达式的值hello,done属性的值false,表示遍历还没有结束。
      next()第二次调用:Generator 函数从上次yield表达式停下的地方,一直执行到下一个yield表达式。next方法返回的对象的value属性就是当前yield表达式的值world,done属性的值false,表示遍历还没有结束。
      next()第三次调用:Generator 函数从上次yield表达式停下的地方,一直执行到return语句(如果没有return语句,就执行到函数结束),next方法返回的对象的value属性,就是紧跟在return语句后面的表达式的值(如果没有return语句,则value属性的值为undefined);此时done为ture,表示遍历结束。

3.3 参数

       在generator函数中可以传递参数,next()方法可以传入实参,这个实参就是前一个yield语句的整体返回结果

	function* gen(arg){
	    console.log(arg);
	    let one=yield 111;
	
	    console.log(one);
	    let two=yield 222;
	    console.log(two);
	    
	    let three=yield 333;
	    console.log(three);
	}
	let result=gen('hello world'); 
	result.next(); //hello world	执行到第一个yield
	result.next('AAA'); //AAA	执行到第二个yield,传递的实参AAA是第一个yield的返回结果
	result.next('BBB');
	result.next();

4 async和await

  async用于申明函数是异步,await用于等待一个异步方法执行完成。

4.1 async函数

  ES2017 标准引入了 async 函数,使得异步操作变得更加方便
  async函数是 Generator 函数的语法糖,与await配合使用;异步编程,同步处理
       1)async函数返回一个 Promise 对象,return语句返回的值,会成为then方法回调函数的参数
       2)async函数内部抛出错误,会导致返回的 Promise 对象变为reject状态。抛出的错误对象会被catch方法回调函数接收到

 async function test(){
	     let res1=await $.get('url');
	     console.log(res1);
	     let res2=await $.get('url');
	     console.log(res2)
	 }
	 test()

4.2 async和generator区别

  async函数对比 generator 函数的优点
       1)async函数内部自带执行器;
       2)更好的语义;async和await,比起星号和yield,语义更清楚。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果
       3)更广的适用性;async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)
       4)返回值是 Promise;async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作

4.3 await

       1)await必须写在 async 函数中
       2)await命令后面是一个 Promise 对象,如果不是,会被转成一个 resolve 的 Promise 对象
       3)await返回结果就是其后面Promise执行的结果,可能是resolved 或 rejected 的值

4.4 promise和await的区别

 1、什么是Async/Await
	 async/await是写异步代码的新方式,使用的方式看起来像同步
	 async/await是基于Promise实现的,它不能用于普通的回调函数。
  2、什么是promise
	 为了解决异步嵌套而产生,让代码更易于理解
	 区别:async/await让代码更像同步,进一步优化了代码
  3. Promise和Async处理失败的时候的区别
    (1)Promise错误可以在构造体里面被捕获,而async/await返回的是promise,可以通过catch直接捕获错误。
    (2)await 后接的Promise.reject都必须被捕获,否则会中断执行
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值