【前端】ES6:Promise对象和Generator函数

文章目录

  • [1 Promise对象](#1 Promise对象)
    • [1.1 回调地狱](#1.1 回调地狱)
    • [1.2 Promise使用](#1.2 Promise使用)
    • [1.3 Promise对象的状态](#1.3 Promise对象的状态)
    • [1.4 Promise.all](#1.4 Promise.all)
    • [1.5 Promise.race](#1.5 Promise.race)
  • [2 Generator函数](#2 Generator函数)
    • [2.1 基本语法](#2.1 基本语法)
    • [2.2 异步流程](#2.2 异步流程)
      • [2.2.1 手动版本](#2.2.1 手动版本)
      • [2.2.2 自动版本](#2.2.2 自动版本)

1 Promise对象

Promise是异步编程的一种解决方案,比传统的解决方案回调函数,更合理和更强大。

ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象 。

  • 指定回调函数方式更灵活易懂。
  • 解决异步 回调地狱 的问题。

1.1 回调地狱

当一个回调函数嵌套一个回调函数的时候,就会出现一个嵌套结构,当嵌套的多了就会出现回调地狱的情况。

比如我们发送三个ajax请求:

  • 第一个正常发送。
  • 第二个请求需要第一个请求的结果中的某一个值作为参数。
  • 第三个请求需要第二个请求的结果中的某一个值作为参数。

回调地狱,其实就是回调函数嵌套过多导致的。

javascript 复制代码
ajax({
  url: '我是第一个请求',
  success (res) {
    // 现在发送第二个请求
    ajax({
      url: '我是第二个请求',
      data: { a: res.a, b: res.b },
      success (res2) {
        // 进行第三个请求
        ajax({
          url: '我是第三个请求',
          data: { a: res2.a, b: res2.b },
  		  success (res3) { 
            console.log(res3) 
          }
        })
      }
    })
  }
})

1.2 Promise使用

javascript 复制代码
new Promise(function (resolve, reject) {
  // resolve 表示成功的回调
  // reject 表示失败的回调
}).then(function (res) {
  // 成功的函数
}).catch(function (err) {
  // 失败的函数
})

1.3 Promise对象的状态

Promise 对象通过自身的状态,来控制异步操作。

Promise 实例具有三种状态。

  • 异步操作未完成(pending)
  • 异步操作成功(fulfilled)
  • 异步操作失败(rejected)

这三种的状态的变化途径只有两种。

  • 从"未完成"到"成功"
  • 从"未完成"到"失败"

一旦状态发生变化,就凝固了,不会再有新的状态变化。这也是Promise这个名字的由来,它的英语意思是"承诺",一旦承诺成效,就不得再改变了。这也意味着,Promise实例的状态变化只可能发生一次。

因此,Promise的最终结果只有两种。

  • 异步操作成功,Promise实例传回一个值(value),状态变为fulfilled。
  • 异步操作失败,Promise实例抛出一个错误(error),状态变为rejected。

1.4 Promise.all

Promise.all()方法用于将多个Promise实例,包装成一个新的Promise实例。

javascript 复制代码
const p = Promise.all([p1, p2, p3]);

p的状态由p1,p2,p3 决定,分成两种情况。

  • 只有p1p2p3的状态都变成fulfilledp的状态才会变成fulfilled,此时p1p2p3的返回值组成一个数组,传递给p的回调函数。
  • 只要p1p2p3之中有一个被rejectedp的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

1.5 Promise.race

Promise.race()方法同样是将多个Promise实例,包装成一个新的Promise实例。

javascript 复制代码
const p = Promise.race([p1, p2, p3]);

上面代码中,只要p1p2p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给p的回调函数。

2 Generator函数

Generator函数是ES6提供的一种异步编程解决方案。

Generator函数是一个状态机,封装了多个内部状态。

执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历Generator函数内部的每一个状态。

2.1 基本语法

js 复制代码
function *gen(){
    console.log(1)
    yield;
    console.log(2)
    yield;
    console.log(3)
}

let g = gen()
g.next()
g.next()
g.next()

yield(产出)表达式是暂停执行的标记,而next方法可以恢复执行。

js 复制代码
function *gen(){
    yield  1;
    yield  2;
}

let g = gen()
let res1 = g.next()
console.log(res1)
let res2 = g.next()
console.log(res2)
let res3 = g.next()
console.log(res3)
js 复制代码
function *gen(){
    let res1 = yield;
    console.log(res1)
    let res2 = yield;
    console.log(res2)
}

let g = gen()
g.next("data-1")
g.next("data-2")
g.next("data-3")
javascript 复制代码
function *gen(){
	let res1 = yield "aaa"//产出
    console.log("gen内部",res1)
	let res2 = yield "bbb"
	console.log("gen内部",res2)
}

let g = gen()
let res1 = g.next("传入-11111") // 第1次next(),到yield停,"aaa"赋值给res1
console.log(res1)               // 打印:aaa
let res2 = g.next("传入-22222") // 第2次next(),将"传入-22222"赋值给let res1 = yield "aaa"中的res1,打印:gen内部,传入-22222,到yield停,"bbb"赋值给res2
console.log(res2)               // 打印:bbb
let res3 = g.next("传入-33333") // 将"传入-33333"赋值给let res2 = yield "bbb"中的res2,打印:gen内部,传入-33333
console.log(res3)               // 打印:undefined

2.2 异步流程

2.2.1 手动版本

js 复制代码
function *gen(){
    let res1 = yield ajax("1.json")
    console.log(res1)
    let res2 = yield ajax("2.json")
    console.log(res2)
}

let g = gen()   

g.next().value.then(data=>{
    g.next(data).value.then(data=>{
        g.next(data)
    })
}) 

//async await 内置自动执行器

2.2.2 自动版本

js 复制代码
function* gen() {
    let res1 = yield ajax("1.json")
    console.log(res1)
    let res2 = yield ajax("2.json")
    console.log(res2)
}


function AutoRun(gen) {
    let g = gen();

    function next(data) {
        let res = g.next(data); // 第1次next()
        if(res.done) return 
        res.value.then(function (data) {
            next(data); // 第2次next()
        });
    }
    next();
}

AutoRun(gen);
相关推荐
魔云连洲6 分钟前
深入解析:Object.prototype.toString.call() 的工作原理与实战应用
前端·javascript·原型模式
JinSo15 分钟前
alien-signals 系列 —— 认识下一代响应式框架
前端·javascript·github
开心不就得了21 分钟前
Glup 和 Vite
前端·javascript
szial23 分钟前
React 快速入门:菜谱应用实战教程
前端·react.js·前端框架
西洼工作室29 分钟前
Vue CLI为何不显示webpack配置
前端·vue.js·webpack
黄智勇1 小时前
xlsx-handlebars 一个用于处理 XLSX 文件 Handlebars 模板的 Rust 库,支持多平台使
前端
brzhang2 小时前
为什么 OpenAI 不让 LLM 生成 UI?深度解析 OpenAI Apps SDK 背后的新一代交互范式
前端·后端·架构
brzhang3 小时前
OpenAI Apps SDK ,一个好的 App,不是让用户知道它该怎么用,而是让用户自然地知道自己在做什么。
前端·后端·架构
爱看书的小沐3 小时前
【小沐学WebGIS】基于Three.JS绘制飞行轨迹Flight Tracker(Three.JS/ vue / react / WebGL)
javascript·vue·webgl·three.js·航班·航迹·飞行轨迹
井柏然4 小时前
前端工程化—实战npm包深入理解 external 及实例唯一性
前端·javascript·前端工程化