抽象表达
具体表达
指定回调函数的方式更加灵活
支持链式调用,可以解决回调地狱问题
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」
保存着异步任务「成功/失败」的结果
如何改变promise的状态?
一个promise指定多个成功/失败回调函数,都会调用吗?
promise如何串连多个操作任务
promise异常穿透?
中断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');
}