抽象表达
Promise是一门新的技术(ES6规范)
Promise是JS中进行异步编程的新解决方案
(旧方案是单纯使用回调函数)
具体表达
从语法上来说:Promise是一个构造函数
从功能上来说:Promise对象用来封装一个异步操作并可以获取其成功或者失败的结果值
指定回调函数的方式更加灵活
旧的:必须在启动异步任务前指定
Promise:启动异步任务 => 返回Promise对象 => 给 Promise对象绑定回调函数(甚至可以在异步任务结束后指定多个)
支持链式调用,可以解决回调地狱问题
什么是回调地狱?回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件
asyncFunc1(opt,(...args1)=>{
asyncFunc2(opt,(...args2)=>{
asyncFunc3(opt,(...args3)=>{
asyncFunc4(opt,(...args4)=>{
// some operation
})
})
})
})
const xhr = new XMLHttpRequest;
xhr.open('GET','https://api.apiopen.top/getJoke');
xhr.send();
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >=200 && xhr.status < 300){
console.log(xhr.response);
}else{
console.log(xhr.status)
}
}
}
const p = new Promise((resolve,reject)=>{
//1、创建对象
const xhr = new XMLHttpRequest;
//2、初始化
xhr.open('GET','https://api.apiopen.top/getJoke');
//3、发送
xhr.send();
//4、处理响应结果
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
//判断响应状态码
if(xhr.status >=200 && xhr.status <300){
//控制台输出响应体
resolve(xhr.response);
}else{
reject(xhr.status);
}
}
}
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
function mineReadFile(path){
return new Promise((resolve,reject)=>{
require('fs').readFile(path,(err,data)=>{
if(err) reject();
resolve();
})
})
}
传入一个遵循常见错误优先的回调风格的函数((err,value) =>...
),并返回一个promise版本
最常见的就是fs的readfile函数
const util = require('util');
const fs = require('fs');
let mineReadFile = util.promisify(fs.readFile);
mineReadFile('./Promise/resource/context.txt').then(res => {
console.log(res.toString(),'haha');
}).catch(err => {
console.log(err)
})
异步操作之后会有三种状态:
实例对象中的另一个属性 「PromiseResult」
保存着异步任务「成功/失败」的结果
执行异步操作成功,执行resolve执行异步操作失败,执行rejectnew PromisePromise对象resolve状态Promise对象reject状态回调onResolved回调onRejected新的Promise对象
如何改变promise的状态?
resolve(value):如果当前是pending就会变为resolved
reject(reason): 如果当前是pending就会变为rejected
抛出异常throw:如果当前是pending就会变为rejected
一个promise指定多个成功/失败回调函数,都会调用吗?
当promise改变为对应状态时都会调用
promise如何串连多个操作任务
promise的then返回一个新的promise,可以看成then()链式调用
通过then的链式调用串连多个同步、异步任务
promise异常穿透?
当使用promise的then链式调用时,可以在最后指定失败的回调
前面任何操作出了异常,都会传到最后失败的回调中处理
中断promise链?
当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数
办法:在回调函数中返回一个pending状态的promise对象
/*
** 手写Promise
*/
function Promise(executor){
}
//添加 then 方法
Promise.prototype.then = function(onResolved,onRejected){}
/*
** 手写Promise
*/
function Promise(executor){
//resolve 函数
function resolve(data){
}
//reject 函数
function reject(data){
}
//同步调用「执行器函数」
executor();
}
//添加 then 方法
Promise.prototype.then = function(onResolved,onRejected){}
/*
** 手写Promise
*/
function Promise(executor){
//添加属性
this.PromiseState = 'pending';
this.PromiseResult = null;
const self = this;
//resolve 函数
function resolve(data){
//1、修改对象的状态
self.PromiseState = 'fulfilled'
//2、设置对象结果值
self.PromiseResult = data
}
//reject 函数
function reject(data){
//1、修改对象的状态
self.PromiseState = 'rejected'
//2、设置对象结果值
self.PromiseResult = data
}
//同步调用「执行器函数」
executor(resolve,reject);
}
//添加 then 方法
Promise.prototype.then = function(onResolved,onRejected){}
使用try{}catch(e)捕捉异常;
try{
executor(resolve,reject);
}catch(e){
reject(e);
}
在resolve,reject函数内部添加if(self.PromiseState !== 'pending') return
语句即可
//添加 then 方法
Promise.prototype.then = function(onResolved,onRejected){
if(this.PromiseState === 'fulfilled'){
onResolved(this.PromiseResult);
}
if(this.PromiseState === 'rejected'){
onRejected(this.PromiseResult);
}
首先存储回调函数,等待状态改变后再执行
//添加 then 方法
Promise.prototype.then = function(onResolved,onRejected){
if(this.PromiseState === 'fulfilled'){
onResolved(this.PromiseResult);
}
if(this.PromiseState === 'rejected'){
onRejected(this.PromiseResult);
}
if(this.PromiseState === 'pending'){
//保存回调函数
this.callback = {
onResolved,
onRejected
}
}
}
function Promise(executor){
//添加属性
this.PromiseState = 'pending';
this.PromiseResult = null;
this.callback = {};
const self = this;
//resolve 函数
function resolve(data){
//1、修改对象的状态
if(self.PromiseState !== 'pending') return
self.PromiseState = 'fulfilled'
//2、设置对象结果值
self.PromiseResult = data
//3、执行回调函数
if(self.callback.onResolved){
self.callback.onResolved(data);
}
}
//reject 函数
function reject(data){
if(self.PromiseState !== 'pending') return
//1、修改对象的状态
self.PromiseState = 'rejected'
//2、设置对象结果值
self.PromiseResult = data
//3、执行回调函数
if(self.callback.onRejected){
self.callback.onRejected(data);
}
}
//同步调用「执行器函数」
try{
executor(resolve,reject);
}catch(e){
reject(e);
}
}
使用数组存储回调函数,通过数组遍历进行调用多个回调函数
this.callbacks = [];//修改为数组
if(this.PromiseState === 'pending'){
//保存回调函数
this.callbacks.push({
onResolved,
onRejected
})
}
//resolve 函数
function resolve(data){
//1、修改对象的状态
if(self.PromiseState !== 'pending') return
self.PromiseState = 'fulfilled'
//2、设置对象结果值
self.PromiseResult = data
//3、执行回调函数
self.callbacks.forEach(item => {
item.onResolved(data)
})
}
//reject 函数
function reject(data){
if(self.PromiseState !== 'pending') return
//1、修改对象的状态
self.PromiseState = 'rejected'
//2、设置对象结果值
self.PromiseResult = data
//3、执行回调函数
self.callbacks.forEach(item => {
item.onRejected(data)
})
}
Promise返回是一个Promise对象
所以:
Promise.prototype.then = function(onResolved,onRejected){
return new Promise((resolve,reject) => {
if(this.PromiseState === 'fulfilled'){
try{
let result = onResolved(this.PromiseResult);
if(result instanceof Promise){
//如果result是一个Promise对象,那么返回的Promise对象的状态根据result的状态来定
result.then(v => {
resolve(v)
},r => {
reject(r)
})
}else{
//对象的状态为「成功」
resolve(result);
}
}catch(e){
reject(e);
}
}
if(this.PromiseState === 'rejected'){
onRejected(this.PromiseResult);
}
if(this.PromiseState === 'pending'){
//保存回调函数
this.callbacks.push({
onResolved,
onRejected
})
}
})
}
const self = this;
...
...
if(this.PromiseState === 'pending'){
//保存回调函数
this.callbacks.push({
onResolved:function(){
try{
let result = onResolved(self.PromiseResult);
if(result instanceof Promise){
result.then(v => {resolve(v)}, r => {reject(r)});
}else{
resolve(result);
}
}catch(e){
reject(e);
}
},
onRejected:function(){
try{
let result = onRejected(self.PromiseResult);
if(result instanceof Promise){
result.then(v => {resolve(v)}, r => {reject(r)});
}else{
resolve(result);
}
}catch(e){
reject(e);
}
}
})
}
对重复性的代码进行封装
Promise.prototype.then = function(onResolved,onRejected){
return new Promise((resolve,reject) => {
const self = this;
function callback(type){
try{
let result = type(self.PromiseResult);
if(result instanceof Promise){
result.then(v => {
resolve(v)
},r => {
reject(r)
})
}else{
//对象的状态为「成功」
resolve(result);
}
}catch(e){
reject(e);
}
}
if(this.PromiseState === 'fulfilled'){
callback(onResolved);
}
if(this.PromiseState === 'rejected'){
callback(onRejected);
}
if(this.PromiseState === 'pending'){
//保存回调函数
this.callbacks.push({
onResolved:function(){
callback(onResolved)
},
onRejected:function(){
callback(onRejected)
}
})
}
})
}
添加catch方法
//添加 catch方法
Promise.prototype.catch = function(onRejected){
return this.then(undefined, onRejected);
}
异常穿透与值传递
Promise.prototype.then = function(onResolved,onRejected){
return new Promise((resolve,reject) => {
const self = this;
//异常穿透
if(typeof onRejected !== 'function'){
onRejected = reason => {
throw reason
}
}
//值传递
if(typeof onResolved !== 'function'){
onResolved = value => value
}
function callback(type){
try{
let result = type(self.PromiseResult);
if(result instanceof Promise){
result.then(v => {
resolve(v)
},r => {
reject(r)
})
}else{
//对象的状态为「成功」
resolve(result);
}
}catch(e){
reject(e);
}
}
if(this.PromiseState === 'fulfilled'){
callback(onResolved);
}
if(this.PromiseState === 'rejected'){
callback(onRejected);
}
if(this.PromiseState === 'pending'){
//保存回调函数
this.callbacks.push({
onResolved:function(){
callback(onResolved)
},
onRejected:function(){
callback(onRejected)
}
})
}
})
}
//添加 Promise.resolve方法
Promise.resolve = function(value){
return new Promise((resolve, reject) => {
if(value instanceof Promise){
value.then(v => {
resolve(v)
}, r => {
reject(r)
})
}else{
resolve(value)
}
})
}
//添加 Promise.reject方法
Promise.reject = function(reason){
return new Promise((resolve, reject) => {
reject(reason)
})
}
//添加 Promise.all 方法
Promise.all = function(promises){
return new Promise((resolve, reject) => {
let count = 0;
let arr = [];
promises.forEach((item, index) => {
item.then(v => {
//每个对象都成功,返回的才会是成功的
count++;
arr[index] = v;
if(count === promises.length){
resolve(arr);
}
}, r => {
reject(r)
})
})
})
}
//添加 Promise.race方法
Promise.race = function(promises){
return new Promise((resolve, reject) => {
promises.forEach((item) => {
item.then(v => {
resolve(v);
}, r => {
reject(r)
})
})
})
}
//Promise.prototype.then
if(this.PromiseState === 'fulfilled'){
setTimeout(() => {
callback(onResolved);
})
}
if(this.PromiseState === 'rejected'){
setTimeout(() => {
callback(onRejected);
})
}
//function Promise()
...
//异步执行回调函数
setTimeout(()=>{
self.callbacks.forEach(item => {
item.onResolved(data)
})
})
async function func(){
return 'promise'
}
console.log(func());
//Promise { 'promise' }
注意:
读取文件内容
const fs = require('fs');
const util = require('util')
const mineReadFile = util.promisify(fs.readFile)
async function main(){
let data = await mineReadFile('./Promise/resource/context.txt');
console.log(data.toString())
}
main();
结合发送AJAX请求
function sendAJAX(url){
const p = new Promise((resolve,reject)=>{
//1、创建对象
const xhr = new XMLHttpRequest;
//2、初始化
xhr.open('GET',url);
//3、发送
xhr.send();
//4、处理响应结果
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
//判断响应状态码
if(xhr.status >=200 && xhr.status <300){
//控制台输出响应体
resolve(xhr.response);
}else{
reject(xhr.status);
}
}
}
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
}
async function awaitAJAX(){
let data = await sendAJAX('https://api.apiopen.top/getJoke');
}
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/xiaotangyu7dong/article/details/126243500
内容来源于网络,如有侵权,请联系作者删除!