Promise学习(一):Promise的理解与简单使用

1. Promise是什么?

1.1 理解

抽象表达:

  • Promise 是一门新的技术(ES6 规范)
  • Promise 是 JS 中进行异步编程的新解决方案(旧方案是单纯使用回调函数)
    具体表达:
  • 从语法上来说: Promise 是一个构造函数
  • 从功能上来说: promise 对象用来封装一个异步操作并可以获取其 成功 / 失败 的结果值

1.2 promise 的状态

promise 的状态: 实例对象中的一个属性 PromiseState

  • pending 未决定的
  • resolved / fulfilled 成功
  • rejected 失败

promise 的状态改变: 只有以下两种情况

  • pending 变为 resolved / fulfilled
  • pending 变为 resolved

1.3 promise的基本流程

Promise学习(一):Promise的理解与简单使用_第1张图片

1.4 Promise的基本使用

1.4.1 使用 Promise 封装基于定时器的异步

function doDelay(time) {
	// 1. 创建 promise 对象(pending 状态), 指定执行器函数
	return new Promise((resolve, reject) => {
		// 2. 在执行器函数中启动异步任务
		console.log('启动异步任务')
		setTimeout(() => {
			console.log('延迟任务开始执行...')
			const time = Date.now() // 假设: 时间为奇数代表成功, 为偶数代表失败
			if (time % 2 === 1) { // 成功了
				// 3. 1. 如果成功了, 调用 resolve()并传入成功的 value
				resolve('成功的数据 ' + time)
			} else { // 失败了
				// 3.2. 如果失败了, 调用 reject()并传入失败的 reason
				reject('失败的数据 ' + time)
			}
		}, time)
	})
}
const promise = doDelay(2000)
promise.then(// promise 指定成功或失败的回调函数来获取成功的 vlaue 或失败的 reason
	value => {// 成功的回调函数 onResolved, 得到成功的 vlaue
		console.log('成功的 value: ', value)
	},
	reason => { // 失败的回调函数 onRejected, 得到失败的 reason
		console.log('失败的 reason: ', reason)
	}
)

1.4.2 使用 Promise 封装 Ajax 异步请求

function promiseAjax(url) {
    return new Promise((resolve, reject) => {
		const xhr = new XMLHttpRequest()
		xhr.onreadystatechange = () => {
			if (xhr.readyState !== 4) return
			const {
				status,
				response
			} = xhr
			// 请求成功, 调用 resolve(value)
			if (status >= 200 && status < 300) {
				resolve(JSON.parse(response))
			} else { // 请求失败, 调用 reject(reason)
				reject(new Error('请求失败: status: ' + status))
			}
		}
		xhr.open("GET", url)
		xhr.send()
    })
}
promiseAjax('https://api.apiopen.top/getJoke?page=1&count=2&type=video')
.then(data => {
	console.log('显示成功数据', data)
},error => {
	alert(error.message)
})

1.4.3 fs模块使用Promise

const fs = require('fs');

function mineReadFile(path){
	return new Promise((resolve, reject) => {
        //读取文件
        require('fs').readFile(path, (err, data) =>{
            //判断
			if(err) reject(err);
			//成功
			resolve(data);
		});
	});
}

mineReadFile('./resource/content.txt')
.then(value=>{
	//输出文件内容
	console.log(value.toString());
}, reason=>{
	console.log(reason);
});

1.4.4 链式调用

  • then方法的返回值也是一个Promise对象,因此可以进行链式调用
  • 异常穿透
    • 当你使用Promise的then,进行链式调用的时候,可以在最后指定失败的回调
    • 前面任何操作出现了异常,都会传递到最后失败的回调中进行处理
let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('第一种err');
    }, 2000)
})
p.then(res => {
    console.log(111); //2s后不会输出111
}).then(res => {
    console.log(222); //2s后不会输出222
}).catch(err => {
    console.log(err) //最终直接走这里哈
})
  • 中断Promise链式操作:
    • 有且只有一种方式去中断Promise,就是让Promise的状态是padding
let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('ok');
    }, 2000)
})

p.then(res => {
    console.log(111)
    //让返回的Promise的状态是padding
    return new Promise(() => {})
}).then(res => {
    console.log(222);
}).catch(err => {
    console.log(err)
})

1.4.5 util.promisify方法

可以将错误优先的回调函数直接变成Promise的封装方式,不用再去手动封装

//引入 util 模块
const util = require('util');
//引入 fs 模块
const fs = require('fs');
//返回一个新的函数
let mineReadFile = util.promisify(fs.readFile);

mineReadFile('./resource/content.txt').then(value => {
  console.log(value.toString());
});

2. 为什么要用Promise?

  • 指定回调函数的方式更加灵活
    • 旧的: 必须在启动异步任务前指定
    • Promise: 启动异步任务 => 返回promie对象 => 给promise对象绑定回调函 数(甚至可以在异步任务结束后指定/多个)
  • 支持链式调用, 可以解决回调地狱问题
    • 终极解决方案:promise +async/await

你可能感兴趣的:(前端学习,Promise,ES6,学习,前端,javascript,es6,promise)