Promise

Promise是JavaScript中处理异步操作的一种新方式,它解决了回调地狱的问题,提供了链式调用和更好的错误处理。本文介绍了Promise的基本概念、构造函数、then和catch方法,以及如何用Promise处理文件读取和Ajax请求。还提到了Node.js的util.promisify方法用于将普通异步函数转换为Promise。此外,讨论了Promise的状态变化和如何通过链式调用来串行执行任务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Promise是什么?

理解

抽象表达

1)Promise是一门新的技术(ES6规范)

2)Promise是js中进行异步编程的新解决方案

备注:旧方案是单纯使用回调函数

具体表达:

1)从语法上来说:Promise是一个构造函数

2)从功能上来说:promise对象用来封装一个异步操作并可以获取其成功/失败的结果值

为什么要用Promise

指定回调函数的方式更加灵活

1)旧的:必须在启动异步任务前指定

2)promise:启动异步任务=》返回promise对象=》给promise对象绑定回调函数(甚至可以在异步任务结束后指定多个)

支持链式调用,可以解决回调地狱问题

1)什么是回调地狱?

回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调执行的条件

2)回调地狱的缺点

不便于阅读

不便于异常处理

3)解决方案

promise链式调用

Promise-fs读取文件

const fs = require('fs')

// 回调函数形式
// fs.readFile('./content.txt',(err,data)=>{
// 	if(err) throw err
// 	console.log(data.toString())
// })

// Promise形式
let p = new Promise((resolve, reject) => {
	fs.readFile('./content.txt', (err, data) => {
		if (err) reject(err)
		resolve(data)
	})
})
p.then(value => {
	console.log(value.toString())
}, reason => {
	console.log(reason)
})

// 封装一个函数mineReadFile读取文件内容
function mineReadFile(path){
    return new Promise((resolve,reject)=>{
        require('fs').readFile(path,(err,data)=>{
            if(err){
                reject(err)
            }else{
                resolve(data)
            }
        })
    })
}

mineReadFile('content.txt').then(value=>{
	console.log(value.toString())
},reason=>{
	console.log(reason)
})

Promise-ajax请求

// 接口地址 https://api.apiopen.top/getJoke
		const btn = document.querySelector('#btn')
		btn.addEventListener('click', function() {

			const p = new Promise((resolve, reject) => {
				// 创建对象
				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) {
							resolve(xhr.response)
						} else {
							reject(xhr.status)
						}
					}
				}
			})

			p.then(value => {
				console.log(value)
			}, reason => {
				console.log(reason)
			})

		})

/*
        封装一个函数sendAJAX发送get ajax请求
        参数 URL
        返回结果Promise对象
        */
       function sendAJAX(url){
           return new Promise((resolve,reject)=>{
               const xhr=new XMLHttpRequest
               xhr.responseType='json'
               xhr.open('get',url)
               xhr.send()
               xhr.onreadystatechange=function(){
                   if(xhr.readyState===4){
                       if(xhr.status>=200 && xhr.status<300){
                           resolve(xhr.response)
                       }else{
                           reject(xhr.status)
                       }
                   }
               }
           })
       }
       sendAJAX('https://api.apiopen.top/getJoke').then(value=>{
           console.log(value);
       },reason=>{
           console.log(reason);
       })

util.promisify方法

util.promisify方法将一个异步函数转换成一个Promise对象,并且返回一个新的函数。

参数:

        fn:需要转换的函数。

        thisArg:可选,指定this对象。

返回值:

        返回一个新的函数,该函数的参数与fn函数的参数相同,并且返回一个Promise对象。

        如果fn函数返回一个Promise对象,则返回的Promise对象的状态和fn函数返回的Promise对象的状态相同。

        如果fn函数返回一个非Promise对象,则返回的Promise对象的状态为resolved,并且返回fn函数返回的非Promise对象。

        如果fn函数抛出一个异常,则返回的Promise对象的状态为rejected,并且返回fn函数抛出的异常。

        如果fn函数返回一个Promise对象,则返回的Promise对象的

// util.promisify方法

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

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

promise的状态改变

实例对象中的一个属性,PromiseState

1.pending变为resolved / fulfilled 成功

2.pending变为rejected 失败

说明:只有这2种,且一个promise对象只能改变一次,无论变为成功还是失败,都会有一个结果数据,成功的结果数据一般称为value,失败的结果数据一般称为reason。

promise对象的值

实例对象中的另一个属性,PromiseResult,保存着异步任务 成功/失败 的结果。通过resolve和reject函数保存。

promise的api

Promise 构造函数: Promise (excutor) {}
        (1) executor 函数: 执行器 (resolve, reject) => {}
        (2) resolve 函数: 内部定义成功时我们调用的函数 value => {}
        (3) reject 函数: 内部定义失败时我们调用的函数 reason => {}
        说明: executor 会在 Promise 内部立即同步调用,异步操作在执行器中执行
Promise.prototype.then 方法: (onResolved, onRejected) => {}
        (1) onResolved 函数: 成功的回调函数 (value) => {}
        (2) onRejected 函数: 失败的回调函数 (reason) => {}
        说明: 指定用于得到成功 value 的成功回调和用于得到失败 reason 的失败回调
返回一个新的 promise 对象
Promise.prototype.catch 方法: (onRejected) => {}
        (1) onRejected 函数: 失败的回调函数 (reason) => {}
        说明: then()的语法糖, 相当于: then(undefined, onRejected)
Promise.resolve 方法: (value) => {}
        (1) value: 成功的数据或 promise 对象
        说明: 返回一个成功/失败的 promise 对象
Promise.reject 方法: (reason) => {}
        (1) reason: 失败的原因
        说明: 返回一个失败的 promise 对象
Promise.all 方法: (promises) => {}
        (1) promises: 包含 n promise 的数组
        说明: 返回一个新的 promise, 只有所有的 promise 都成功才成功, 只要有一个失败了就
直接失败
Promise.race 方法: (promises) => {}
        (1) promises: 包含 n promise 的数组
        说明: 返回一个新的 promise, 第一个完成的 promise 的结果状态就是最终的结果状态

Promise关键问题

如何改变 promise 的状态?
        (1) resolve(value): 如果当前是 pending 就会变为 resolved
        (2) reject(reason): 如果当前是 pending 就会变为 rejected
        (3) 抛出异常: 如果当前是 pending 就会变为 rejected
一个 promise 指定多个成功/失败回调函数, 都会调用吗?
        当 promise 改变为对应状态时都会调用
改变 promise 状态和指定回调函数谁先谁后?
        (1) 都有可能, 正常情况下是先指定回调再改变状态, 但也可以先改状态再指定回调
        (2) 如何先改状态再指定回调?
                ① 在执行器中直接调用 resolve()/reject()
                ② 延迟更长时间才调用 then()
        (3) 什么时候才能得到数据?
                ① 如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据
                ② 如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据
promise.then()返回的新 promise 的结果状态由什么决定?
        (1) 简单表达: then()指定的回调函数执行的结果决定
        (2) 详细表达:
                ① 如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常
                ② 如果返回的是非 promise 的任意值, promise 变为 resolved, value 为返回的值
                ③ 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果
promise 如何串连多个操作任务?
        (1) promise 的 then()返回一个新的 promise, 可以看成 then()的链式调用
        (2) 通过 then 的链式调用串连多个同步/异步任务
promise 异常传透?
        (1) 当使用 promise then 链式调用时, 可以在最后指定失败的回调,
        (2) 前面任何操作出了异常, 都会传到最后失败的回调中处理
中断 promise ?
        (1) 当使用 promise then 链式调用时, 在中间中断, 不再调用后面的回调函数
        (2) 办法: 在回调函数中返回一个 pendding 状态的 promise 对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值