Promise 知识点集合

多层回调函数的相互嵌套,就形成了回调地狱

回调地狱的缺点:

    代码耦合性太强,牵一发而动全身,难以维护

    大量冗余的代码相互嵌套,代码的可读性变差

    setTimeout(()=>{//第一层回调函数

        setTimeout(()=>{//第二层回调函数

            setTimeout(()=>{第三层回调函数

            },3000)

        },7000)

    },1000)

     如何解决回调地狱的问题

为了解决回调地狱的问题,ES6中新增了promise的概念

     Promise的基本概念

     promise 是一个构造函数

        我们可以创建promise 的实例 const p = new Promise()

        new 出来的Promise 实例对象,代表一个异步操作

     Promise.prototype 上包含一个 .then()方法

        每一次 new Promise() 构造函数得到的实例对象

        都可以通过原型链的方式访问到.then() 方法,例如 p.then()

    .then() 方法用来预先 指定成功和失败的回调函数

        p.then(成功的回调函数,失败的回调函数)

        p.then(result=>{},error=>{})

        调用.then() 方法时,成功的回调函数是必选的,失败的回调函数是可选的

    then-fs 的基本使用

由于node.js官方提供的fs模块仅支持以回调函数的方式读取文件,不支持Promise的调用方式。因此,需要先运行如下的命令,安装then-fs这个第三方包,从而支持我们基于Promise的方式读取文件的内容:

npm install then-fs

调用then-fs 提供的readFile() 方法,可以异步地读取文件的内容,它的返回值Promise的实例对象。因此可以调用 .then()方法为每个Promise异步操作指定成功和失败之后的回调函数。

    /***

    * 基于Promise 的方式读取文件

    */

     

    import thenFs from 'then-fs'

     

    //注意 .then() 中的失败回调是可选的,可以被省略

   

    thenFs.readFile('./files/1.txt','utf8').then(r1=>{console.log(r1)},err1=>{})

    thenFs.readFile('./files/1.txt','utf8').then(r1=>{console.log(r1)},err1=>{})

    thenFs.readFile('./files/1.txt','utf8').then(r1=>{console.log(r1)},err1=>{})

    //注意:上述的代码无法保证文件的读取顺序,需要做进一步的改进!

.then的特性:如果上一个.then()方法中返回一个新的Promise实例对象,则可以通过下一个.then()继续进行处理。通过.then()方法的链式调用,就解决了回调地狱的问题

 Ptomise支持链式调用,从而来解决回调地狱的问题。代码如下:

在promise的链式操作中如果发生了错误,可以使用promise.prototypy.catch方法进行捕获和处理


   

 thenFs.readFile('./files/1.txt','utf8')

        .catch(err=>{ //放到前面  可以捕获第一行的错误,并输出错误信息

        console.log(err.message)// 由于错误已被处理,所以并不影响后续.then 的正常执行

        })

        .then(r1=>{  // Ptomise支持链式调用

        console.log(r1)

        rutern thenFs.readFile('./files/2.txt','utf8')

        })

        .then(r2=>{  // Ptomise支持链式调用

        console.log(r2)

        rutern thenFs.readFile('./files/3.txt','utf8')

        })

        .then(r3=>{  // Ptomise支持链式调用

        console.log(r3)

        })

        .catch(err=>{ //放到最后可以捕获前面发生的所有错误,并输出错误的信息

        console.log(err.message)

        })

    Promise.all方法

Promise.all() 方法会发起并行的Promise异步操作,等所有的异步操作全部结束后才会执行下一步的.then 操作(实现一个等待机制)

    1.定义一个数组,存放3个读取文件的异步操作

    const promiseArr=[

        thenFs.readFile('./files/1.txt','utf8'),

        thenFs.readFile('./files/2.txt','utf8'),

        thenFs.readFile('./files/3.txt','utf8'),

    ]

     

    2.将Promise 的数组,作为Promise.all() 的参数

     

    Promise.all(promiseArr)

         //所有文件读取成功(等待机制) 数组中的文件读取顺序就是.then中结果返回的顺序

        .then( result=>{

        console.log(r1,r2,r3)

        })

        .catch(err=>{  //捕获promise 异步操作中的错误

        console.log(err.message

        })

    Promise.race()方法

Promise.race()方法会发起并行的Promise异步操作,只要任何一个异步操作完成,就立即执行下一步的.then 操作(赛跑机制)。

    1.定义一个数组,存放3个读取文件的异步操作

    const promiseArr=[

        thenFs.readFile('./files/1.txt','utf8'),

        thenFs.readFile('./files/2.txt','utf8'),

        thenFs.readFile('./files/3.txt','utf8'),

    ]

     

    2.将Promise 的数组,作为Promise.all() 的参数

     

    Promise.race(promiseArr)

         //数组中执行最快的那一个异步操作的值

        .then( result=>{

        console.log(r1,r2,r3)

        })

        .catch(err=>{  //捕获promise 异步操作中的错误

        console.log(err.message

        })

    基于Promise 封装读文件的方法

方法的封装要求:

    方法的名称要定义为getFile

    方法接受一个形参fpath,表示读取的文件路径

    方法的返回值为一个Promise 实例对象

创建具体的异步操作

如果想要创建具体的异步操作,则需要在new Promise() 构造函数期间,传递一个function函数,将具体的异步操作定义到function函数内部


 

   //1.方法的名称为 getFile   读文件的异步操作

    //2.方法接受一个形参fpath 表示要读取的文件的路径

    function getFile(fpath){

     

    //3.方法的返回值为Promise 的实例对象

        return new Promise(function (resolve,reject ){

     

        //4.下面这行代码,表示这是一个具体的、读文件的异步操作

        fs.readFile(fpath,'utf8',(err,dataStr)={

            //返回值

            if(err) return reject(err)

            resolve(dataStr)    

            })

        })

    }

     

    //getFile 方法的调用过程

     

    getFile('读取文件的路径').then(成功的回调,失败的回调)

 在请求一个接口拿到一个数组,使用该数组id循环去请求一个接口拿到数据时执行的操作:

//先定义一个空数组
let spreadList = []
//A接口,这里简单写一下,部分参数省略了
uni.request({
	url: A,
	success: (res) => {
		//res.list为请求成功后返回的数组,这里拿数组里每个对象的id字段请求B接口
		res.list.forEach(item => {
			spreadList.push(
				new Promise((resolve, reject) => {
				//请求B接口
					uni.request({
						url: B,
						data: {
							id: item.id
						},
						success(response => {
						//responseB接口返回的一个对象
							item.obj = response
							resolve(item)
						})
					})
				})
			)
		})
		Promise.all(spreadList).then(res => {
		//这里的list则是页面渲染的内容
			this.list = res
		})
	}
})

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LXXgalaxy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值