Nodejs 之 promise

本文介绍了Node.js中Promise的概念,旨在解决回调地狱问题。Promise有三种状态:Pending、Fulfilled和Rejected,且状态一旦改变不可逆。通过Promise可以更灵活地指定回调函数,支持链式调用。此外,文章还探讨了async/await的使用,以及Promise的关键问题,如状态改变、回调函数的调用时机等。

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

一、CommonJs

  • JavaScript 是一个强大面向对象语言,它有很多快速高效的解释器。然而, JavaScript标准定义的 API 是为了构建基于浏览器的应用程序。并没有制定一个用于更广泛的应用程序的标准库。

  • CommonJS 规范的提出,主要是为了弥补当前 JavaScript 没有标准库的缺陷。它的终极目标就是:提供一个类似 Python,Ruby 和 Java 语言的标准库,而不只是让 JavaScript 停留在小脚本程序的阶段。用 CommonJS API 编写出的应用,不仅可以利用 JavaScript 开发客户端应用,而且还可以编写以下应用。
    1. 服务器端 JavaScript 应用程序。(nodejs)
    2. 命令行工具。
    3. 桌面图形界面应用程序。

  • CommonJS 就是模块化的标准,nodejs 就是 CommonJS(模块化)的实现。

二、Promise

2.1 回调地狱

由多层嵌套的回调函数组成的代码称为回调地狱,多数在写阻塞执行代码的时候会产生。回调地狱的代码可读性差,很难让人弄清楚业务逻辑。

function callbackFn(callback){
       setTimeout(function(){
   callback()
        },1000)
}
callbackFn(function(){
      callbackFn(function(){
   callbackFn(function(){
   	callbackFn(function(){console.log('回调结束')})
         })
             })
})

上面的代码执行4秒后会输出’回调结束‘,虽然达到了我们要阻塞执行的目的,但是非常不容易让人读懂,且书写麻烦

2.2 promise是什么

2.2.1 抽象表达

  1. Promise是一门新的技术(ES6规范)
  2. Promise是JS中进行异步编程的新解决方案
    备注:旧方案是单纯使用回调函数

2.2.2 具体表达

  1. 从语法上来说: Promise是一个构造函数
  2. 从功能上来说: Promise对象用来封装一个异步操作并可以获取其成功/失败的结果值

2.2.3 Promise有三个状态

  • Pending:异步的事情正在执行;
  • Fulfilled:异步的事情成功了;
  • Rejected:异步的事情失败了

2.2.4 promise的状态改变

  1. pending变为resolved
  2. pending变为rejected

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

2.3 promise基本流程

在这里插入图片描述

2.4 promise的优势

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

  1. 旧的: 必须在启动异步任务前指定
  2. promise: 启动异步任务=> 返回promie对象=> 给promise对象绑定回调函数(甚至可以在异步任务结束后指定/多个)

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

  1. 什么是回调地狱?
    回调函数嵌套调用, 外部回调函数异步执行的结果是嵌套的回调执行的条件
  2. 回调地狱的缺点?
    不便于阅读,不便于异常处理
  3. 解决方案?
    promise链式调用
  4. 终极解决方案?
    async/await

2.5 promise的使用:解决回调地狱问题

/*回调地狱*/

doSomething(function(result){
	doSomethingElse(result,function(newResult){
		doThirdThing(newResult,function(finalResult){
				console.log('Gotthefinalresult:'+finalResult)
		},failureCallback)
	},failureCallback)
},failureCallback)
/*使用promise的链式调用解决回调地狱*/

doSomething().then(function(result){
	    return doSomethingElse(result)})
   .then(function(newResult){
		return doThirdThing(newResult)})
   .then(function(finalResult){
	    console.log('Gotthefinalresult:'+finalResult)})
	.catch(failureCallback)
		
function  doDelay(time){
	//1.创建promise对象
	return new Promise((resolve,reject)=>{
	//2.启动异步任务
	console.log('启动异步任务') ;
	setTimeout(()=>{
		console.log('延迟任务开始执行...')
		const time = Date.now()
		//假设:时间为奇数代表成功,为偶数代表失败
		if(time % 2 === 1){
			//成功了
			//3.1.如果成功了,调用resolve()并传入成功的value
			resolve('成功的数据'+time)
		}else{
			//失败了
			//3.2.如果失败了,调用reject()并传入失败的reason
			reject('失败的数据'+time)
		}},time)
	 })
}

const  promise = doDelay(2000) ;
promise.then(value=>{
	console.log('成功的value:',value)},
	         reason=>{
	console.log('失败的reason:',reason)},)

2.6 async/await 同时使用

  1. async 是“异步”的简写,而 await 可以认为是 async wait 的简写。所以应该很好理解 async用于申明一个异步的 function ,而 await 用于等待一个异步方法执行完成。
  2. 简单理解:
    async 是让方法变成异步。
    await 是等待异步方法执行完成。
  3. 详细说明:
    async 是让方法变成异步,在终端里用 node 执行这段代码,你会发现输出了 Promise {‘Hello async’ },这时候会发现它返回的是 Promise。
async function testAsync(){
	return 'Hello async';
}
const result = testAsync();
console.log(result);
  1. await 在等待 async 方法执行完毕,其实 await 等待的只是一个表达式,这个表达式在官方文档里说的是 Promise 对象,但是它也可以接受普通值。
  2. 注意:await 必须在 async 方法中才可以使用因为 await 访问本身就会造成程序停止堵塞,所以必须在异步方法中才可以使用
  3. async 会将其后的函数(函数表达式或 Lambda)的返回值封装成一个 Promise 对象,而await 会等待这个 Promise 完成,并将其 resolve 的结果返回出来。

2.7 Promise的使用

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

2.8 Promise的几个关键问题

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值