Javascript 中的神器 — — Promise(解决回调地狱)

Promise 概述

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

它由社区最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了Promise对象。

所谓Promise,简单说就是一个容器, 里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。

从语法上说,Promise是一个对象,从它可以获取异步操作的消息。

Promise 提供统一的API,各种异步操作都可以用同样的方法进行处理。

Promise 对象代表一个异步操作:
有三种状态:pending(进行中)、fulfilled (已成功)和rejected (已失败)Promise对象的状态改变,只有两种可能:
1、成功:从pending变为fulfilled
2、失败:从pending变为rejected。

只有异步操作的结果,可以决定当前是哪一种状态, 任何其他操作都无法改变这个状态。

这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。


ajxa和axios也会返回promise对象(有些方法自身便会返回promise对象,不用去手写promise对象)

Promise 语法

ES6规定,Promise对象是一个构造函数,用来生成Promise实例

Promise 构造函数接受一个函数作为参数,
这个作为参数的函数,也有俩个参数,该函数的俩个参数分别是resolve和reject
这俩个参数也是函数,由JavaScript 引擎提供,不用自己部署

异步操作成功后,调用resolve()方法,其内部调用了then()里面的第一个参数函数
异步操作失败后,调用reject()方法,其内部调用了then()里面的第二个参数函数

例如:

const fs=require('fs')

let p=new Promise((resolve,reject)=>{
    //写异步操作(读文件)
    fs.readFile(`${__dirname}/file/aa.txt`,'utf-8',(err,data)=>{
        if(err){
            //文件读取失败
            reject(err)  // 调用then() 里面第二个参数函数
        }else{
            //文件读取成功
            resolve(data)//调用then() 里面第一个参数函数
        }
    })
})

p.then((data)=>{
    console.log(data)
},(err)=>{
    console.log(err)
})

/*上面p对象中写异步操作,这个对象会直接执行。*/

-----------------------------------------------------------------------------------------当然也可以为其封装一个函数,以后调用时再执行,例如:

function getPromise(){
    return new Promise((resolve,reject)=>{
    //写异步操作(读文件)
    fs.readFile(`${__dirname}/file/aa.txt`,'utf-8',(err,data)=>{
        if(err){
            //文件读取失败
            reject(err)  // 调用then() 里面第二个参数函数
        }else{
            //文件读取成功
            resolve(data)//调用then() 里面第一个参数函数
        }
    })
})
}

getPromise().then((data)=>{
    console.log(data)
},(err)=>{
    console.log(err)
})

回调地狱概述

假如需求是依次去执行异步代码(异步操作无顺序),而且是顺序执行

那么做法是在异步请求成功后的回调函数中,再去执行下一个异步请求

但是会出现回调地狱,例如:

/*
补充知识:
在一个回调函数中嵌套回调函数,不断的进行嵌套,代码阅读性地,维护不变,让人觉得害怕,这样就是回调地狱
*/

//导包
const fs=require('fs')

//读a文件
fs.readFile(`${__dirname}/file/a.txt`,'utf-8',(err,data)=>{
    if(err){
        console.log(err);
    }else{
        console.log(data); 
        
        //读b文件
        fs.readFile(`${__dirname}/file/b.txt`,'utf-8',(err,data)=>{
            if(err){
                console.log(err);
            }else{
                console.log(data);  

                //读c文件
                fs.readFile(`${__dirname}/file/c.txt`,'utf-8',(err,data)=>{
                    if(err){
                        console.log(err);
                    }else{
                        console.log(data);  
                    }
                })
            }
        })
    }
})


解决回调地狱

//导包
const fs=require('fs')

function getPromise(filename){
    return new Promise((resolve,reject)=>{
    //写异步操作(读文件)
    fs.readFile(`${__dirname}/file/${filename}.txt`,'utf-8',(err,data)=>{
        if(err){
            //文件读取失败
            reject(err)  // 调用then() 里面第二个参数函数
        }else{
            //文件读取成功
            resolve(data)//调用then() 里面第一个参数函数
        }
    })
})
}

getPromise('a').then((data)=>{
    console.log(data)
    
    //调用getPromise(),此时传入的参数是b文件,并返回
    //return 返回的整体再去执行下一个then
    return getPromise('b')
},(err)=>{
    console.log(err)
}).then((data)=>{
    console.log(data)
    return getPromise('c')
}).then((data)=>{
    console.log(data)
},(err)=>{
    console.log(err)
})

Promise 方法补充

catch()
抓取错误信息,这样在每个文件后面省略了 (err)=>{console.log(err)}
只需要再最后写个文件后面 catch((err)=>{console.log(err)})

例如:

//导包
const fs=require('fs')

function getPromise(filename){
    return new Promise((resolve,reject)=>{
    //写异步操作(读文件)
    fs.readFile(`${__dirname}/file/${filename}.txt`,'utf-8',(err,data)=>{
        if(err){
            //文件读取失败
            reject(err)  // 调用then() 里面第二个参数函数
        }else{
            //文件读取成功
            resolve(data)//调用then() 里面第一个参数函数
        }
    })
})
}

getPromise('a').then((data)=>{
    console.log(data)
    
    //调用getPromise(),此时传入的参数是b文件,并返回
    //return 返回的整体再去执行下一个then
    return getPromise('b1')
}).then((data)=>{
    console.log(data)
    return getPromise('c')
}).then((data)=>{
    console.log(data)
}).catch((err)=>{
    console.log(err)
})

all()
用于将多个promise实例,包装成一个新的promise实例
所有promise对象执行成功,all才会成功(相对于并且)

//导包
const fs=require('fs')

function getPromise(filename){
    return new Promise((resolve,reject)=>{
    //写异步操作(读文件)
    fs.readFile(`${__dirname}/file/${filename}.txt`,'utf-8',(err,data)=>{
        if(err){
            //文件读取失败
            reject(err)  // 调用then() 里面第二个参数函数
        }else{
            //文件读取成功
            resolve(data)//调用then() 里面第一个参数函数
        }
    })
})
}

let p1=getPromise('a')
let p2=getPromise('b')
let p3=getPromise('c')

let pAll=Promise.all([p1,p2,p3])
//每一个promise对象(p1,p2,p3)都读取成功,最后才会成功
pAll.then((data)=>{
    console.log(data)
})
race()
此方法和all()类似,但是只要一个promise执行成功,那么race就成功(相当于或者)

例如:

//导包
const fs=require('fs')

function getPromise(filename){
    return new Promise((resolve,reject)=>{
    //写异步操作(读文件)
    fs.readFile(`${__dirname}/file/${filename}.txt`,'utf-8',(err,data)=>{
        if(err){
            //文件读取失败
            reject(err)  // 调用then() 里面第二个参数函数
        }else{
            //文件读取成功
            resolve(data)//调用then() 里面第一个参数函数
        }
    })
})
}

let p1=getPromise('a')
let p2=getPromise('b')
let p3=getPromise('c')

let pAll=Promise.race([p1,p2,p3])
//每一个promise对象(p1,p2,p3)有一个读取成功,race便会成功(每次执行后便会随机读一个文件)
pAll.then((data)=>{
    console.log(data)
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值