12.4 生成器函数实例 - 2
// 模拟 先获取用户数据,获取用户的订单信息,获取订单的商品数据 function getUsers() { setTimeout(() => { let user = '用户数据' // 第一个片段的数据传给第二个片段 // 调用第二个next并传参 // 相当于第一个yield返回值 i.next(user) }, 1000) } function getOrders( users ) { console.log(users) setTimeout(() => { let order = '订单信息' i.next(order) }, 1000) } function getGoods( orders ) { console.log(orders) setTimeout(() => { let good = '商品数据' i.next(good) }, 1000) } // 声明生成器函数 function * gen() { let users = yield getUsers() let orders = yield getOrders(users) let goods = yield getGoods( orders ) console.log(goods) } // 迭代器对象 let i = gen() i.next()
13. Promise
【Promise(简介、基本使用、API、手写实现 Promise、async与await)】
Promise 是 ES6 引入的异步编程的新解决方案。(解决回调地狱)
语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
13.1 Promise 基本使用
// 创建一个Promise对象,Promise对象有三个状态 // 刚实例的promise对象的状态为pending // 需要传入一个参数,参数为函数 // 函数需要两个参数,一个为成功的函数,可以将promise的状态改为成功 // 另一个参数为失败的函数,可以将promise的状态改为失败 const p1 = new Promise((resolve, reject) => { // 成功 let data = '数据中的数据' resolve(data) }) // promise对象可以通过then指定成功和失败的回调函数 // 第一个参数为成功的回调函数 // 第二个参数为失败的回调函数 p1.then( (value) => { console.log(value) }, (reason) => { console.log(reason) } ) const p2 = new Promise((resolve, reject) => { // 失败 let data = '从数据库获取数据失败' reject(data) }) p2.then( (value) => { console.log(value) }, (reason) => { console.log(reason) } )
13.2 Promise 封装读取文件
使用 js 读取文件要在 Node.js 环境下
fs模块读取文件:
// 导入fs模块 const fs = require('fs') // 读取文件 // 第一个参数为读取文件的路径 // 第二个参数为回调函数(回调函数第一个参数为失败的对象,第二个参数为读取到的数据) fs.readFile('./00-文本文件.txt', (err, data) => { if (err) console.log(err) console.log(data.toString()) })
使用Promise封装fs读取文件:
const p = new Promise((resolve, reject) => { fs.readFile('./00-文本文件.txt', (err, data) => { if (err) reject(err) resolve(data.toString()) }) }) p.then(value => { console.log(value) }, reason => { console.log(reason) })
13.3 Promise 封装AJAX
原生AJAX:
<body> <script> // 原生AJAX // 创建发送AJAX请求的对象 const xhr = new XMLHttpRequest() // 初始化请求对象 xhr.open('GET', 'http://127.0.0.1:8000') // 设置请求头 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') // 发送请求 xhr.send() // 处理请求响应回来的数据 xhr.onreadystatechange = function() { if (xhr.readyState === 4) { if ( xhr.status>=200 && xhr.status<300 ) { console.log(xhr.response) // 打印响应回来的数据 } } } </script> </body>
服务端代码:
// 导入express const express = require('express') // 创建应用对象 const app = express() // 创建路由对象 // request 是对请求报文的封装 // response 是对响应报文的封装 app.get('/', (request, response) => { //设置响应头 设置允许跨域 response.setHeader('Access-Control-Allow-Origin', '*'); // 向客户端发送数据 response.send('Hello AJAX') }) app.post('/', (request, response) => { //设置响应头 设置允许跨域 response.setHeader('Access-Control-Allow-Origin', '*'); response.setHeader('Access-Control-Allow-Headers', '*'); response.setHeader('Access-Control-Allow-Methods', '*'); response.setHeader('Access-Control-Expose-Headers', '*'); // 向客户端发送数据 response.send('Hello AJAX POST') }) // 启动服务器进行监听 // 8000 端口 服务端在8000端口监听客户端向8000端口发送过来的请求 app.listen(8000, () => { console.log('服务端在8000端口监听') })
使用Promise封装:
<body> <script> const p = new Promise((resolve, reject) => { // 创建发送AJAX请求的对象 const xhr = new XMLHttpRequest() // 初始化请求对象 xhr.open('GET', 'http://127.0.0.1:8000') // 设置请求头 xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded') // 发送请求 xhr.send() // 处理请求响应回来的数据 xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status >= 200 && xhr.status < 300) { // 成功 resolve(xhr.response) } else { // 失败 reject(xhr.status) } } } }) // 回调 p.then( (value) => { console.log(value) }, (reason) => { console.log(reason) } ) </script> </body>
13.4 Promise.prototype.then()
Promise.prototype.then()的返回结果也为一个Promise对象。
const p1 = new Promise((resolve, reject)=>{ setTimeout(()=>{ resolve('用户数据') },1000) }) const res1 = p1.then(v=>{ console.log(v) }, r=>{ console.log(r) }) console.log(res1)
fulfilled表示成功的状态
then()返回的Promise对象的状态由回调函数的执行结果决定。
- 如果回调函数中返回的结果是 非 promise 类型的属性, 状态为成功, 返回值为对象的成功的值
const p1 = new Promise((resolve, reject)=>{ setTimeout(()=>{ resolve('用户数据') },1000) }) const res1 = p1.then(v=>{ // console.log(v) return 123 }, r=>{ console.log(r) }) console.log(res1)
- 是 promise 对象,返回的Promise对象的状态由return的Promise对象的状态决定,返回的Promise对象的结果,为return的promise对象的结果
const p1 = new Promise((resolve, reject)=>{ setTimeout(()=>{ resolve('用户数据') },1000) }) const res1 = p1.then(v=>{ // console.log(v) return new Promise((reso, reje)=>{ reso() }) }, r=>{ console.log(r) }) console.log(res1)
const p1 = new Promise((resolve, reject)=>{ setTimeout(()=>{ resolve('用户数据') },1000) }) const res1 = p1.then(v=>{ // console.log(v) return new Promise((reso, reje)=>{ reje('ERRor') }) }, r=>{ console.log(r) }) console.log(res1)
rejected表示失败的状态
- 抛出错误,返回的为失败状态的promise对象,错误信息为返回的promise对象的结果
const p1 = new Promise((resolve, reject)=>{ setTimeout(()=>{ resolve('用户数据') },1000) }) const res1 = p1.then(v=>{ // console.log(v) throw 'ERROR' }, r=>{ console.log(r) }) console.log(res1)
由于then返回的为promise对象,所以promise可以链式调用:
//链式调用 p.then(value=>{ }).then(value=>{ });