1. 基本概念
在 JavaScript 里,异步操作十分常见,像网络请求、文件读取等。以往,处理异步操作通常采用回调函数的方式,但这种方式在处理多个异步操作嵌套时,会让代码变得复杂难读,也就是所谓的 “回调地狱”。Promise 正是为解决这一问题而出现的。
Promise 代表一个异步操作的最终完成或者失败,并且返回其结果。它有三种状态:
-
pending(进行中) :初始状态,既不是成功,也不是失败状态。
-
fulfilled(已成功) :意味着操作成功完成。
-
rejected(已失败) :表示操作失败。
Promise 的状态一旦从 pending 变为 fulfilled 或者 rejected,就不会再改变。
2. 创建 Promise
Promise构造函数 创建一个 Promise 实例需要传入一个执行器函数(executor),这个执行器函数接收两个参数:resolve 和 reject,它们都是函数。
executor函数:执行器 (resolve,reject)=>{}
executor会在Promise内部立即同步调用。异步操作在执行器中执行
3. 处理 Promise 结果
使用 then 方法处理 Promise 成功的结果,使用 catch 方法处理 Promise 失败的结果。
4. Promise 的链式调用
javascript
function asyncOperation1() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('操作 1 完成');
}, 1000);
});
}
function asyncOperation2(result) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(result + ',操作 2 完成');
}, 1000);
});
}
asyncOperation1()
.then(asyncOperation2)
.then((finalResult) => {
console.log(finalResult); // 输出:操作 1 完成,操作 2 完成
})
.catch((error) => {
console.error(error);
});
在这个例子中,asyncOperation1 和 asyncOperation2 都是返回 Promise 实例的异步函数。通过 then 方法将它们链式调用,实现了按顺序执行异步操作。
5. 静态方法
- Promise.all:接收一个
Promise数组,当所有Promise都成功时,返回一个新的Promise,其结果是一个包含所有Promise结果的数组;只要有一个Promise失败,就会立即返回一个失败的Promise。 - Promise.race:接收一个
Promise数组,只要其中一个Promise状态改变(成功或失败),就会返回这个Promise的结果。 -
总结
Promise 是 JavaScript 中处理异步操作的强大工具,它通过状态管理和链式调用,让异步代码的编写和维护更加简单和清晰。同时,Promise 的静态方法也提供了处理多个异步操作的便捷方式。
Promise手写题
手写 Promise
class Promise{ //类
constructor (executor){
this.status='pending'
this.value=undefined //成功的结果
this.reason=undefined //失败的原因
//存放成功的回调
this.onResolvedCallbacks = [];
//存放失败的回调
this.onRejectedCallbacks = [];
}
//resolve 函数
let resolve=(value)=>{
if(this.status === 'pending')
{ this.value = value;
this.status = "resolved";
this.onResolvedCallbacks.forEach(fn => fn()); } }// 执行所有成功的回调函数
//reject 函数
let reject=(reason)=>{
if(this.status==='pending'){
this.reason=reason
this.status='pengding'
this.onRejectedCallbacks.forEach(fn=>fn() // 执行所有失败的回调函数
}
//考虑到异常情况
try{
executor(resolve,reject) //executor 函数立即执行
}catch(e){
reject(e)} // 如果 executor 函数抛出异常,调用 reject 方法
}
}
手写 Promise.all
Promise.all=function(promises)//传入一个数组{
return new Promise((resolve,reject)=>{
let count=0 //计数器
let result=[] //保存结果的数组
for(let i=0;i<promises.length){
promises[i].then(v=>{
count++
result[i]=v //将每一个promise的结果存入数组中
if(count===promises.length){resolve (result)} //判断是否都执行完毕,将结果resolve
},r=>{
reject(r)
}
v 和 r 都是then 回调函数里面的
手写 Promise.race
Promise.race=function(promises){
return new Promise((resolve,reject)=>{
for(let i=0;i<promises.length){
promises[i].then(v=>{ resolve(v)}, //只要有一个promise成功/失败,就立马返回结果
r=>{reject(r) })
}
})
手写 Promise 封装 ajax请求
function sendAjax(url){
return new Promise((resolve,reject)=>{
const xhr=new XMLHttpRequest() //创建对象
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)} //状态码
}
}
})
}
参考资料
promise.resolve()方法
传入的参数是非Promise 类型的对象,返回的结果是 成功的promise对象
传入的参数是Promise对象,则参数的结果 决定了resolve的结果
执行结果:success undefined
过程是 第一个 then 返回的是新的promise对象,返回的success
所以可以调用第二个 then 方法 打印success
但是第二个then 没有返回结果 所以返回的是一个成功的promise,成功的值没有定义 所以第三个then是undefined
原理:then的返回结果也是promise