JavaScript promise 常见用法
2023-05-14 本文已影响0人
暴躁程序员
promise 的出现是为了解决回调函数的两个常见问题
// 回调函数问题
问题一:回调函数多层嵌套调用(回调地狱)
问题二:每次回调的结果存在成功或失败的可能性
// 使用 promise 解决
解决问题一:promise 通过 .then 实现链式调用
解决问题二:promise 通过 .catch 统一捕获异常
1. promise对象上的 then、catch、finally 方法
- .then(回调函数) : resolve(e) 出口,可链式调用
- .catch(回调函数) :reject(e) 出口或者用于捕获程序异常
- .finally(回调函数):总是在最后执行
- 新建 promise.js
const getData = (params) => {
return new Promise((resolve, reject) => {
// throw new Error() // 可被 catch 捕获
if (params?.id) {
setTimeout(() => {
resolve({
errorCode: "0",
data: {
id: params.id,
message: "hello promise",
},
});
}, 1000);
} else {
setTimeout(() => {
reject({
errorCode: "-1",
data: {
message: "no params",
},
});
}, 1000);
}
});
};
const params = { id: 1 }
getData(params)
.then((res) => {
console.log('res',res);
})
.catch((err) => {
console.log('err',err);
})
.finally(() => {
console.log("我是 finally 总是最后执行");
});
- 终端执行
node promise.js
- 结果
// 2s 后
res { errorCode: '0', data: { id: 1, message: 'hello promise' } }
我是 finally 总是最后执行
2. promise 对象简化写法,Promise.resolve()、Promise.reject()
- 新建 promise.js
const resolve = Promise.resolve("hello Promise.resolve");
resolve.then((res) => {
console.log(res);
});
const reject = Promise.reject("hello Promise.reject");
reject.catch((err) => {
console.log(err);
});
- 终端执行
node promise.js
- 结果
hello Promise.resolve
hello Promise.reject
3. 等所有 promise 异步执行完毕统一返回结果(短路),Promise.all([p1,p2,p3])
- Promise.all() 接受一个由promise对象组成的数组:如果传入函数返回的promise对象,需要传入函数立即执行后的结果
- 特点:短路,必须所有的都是 resolve 否则才返回所有结果,否则发现第一个 reject 就直接返回那个 reject的结果
- 获取结果(全部 resolve):按照 [fn1,fn2,fn3] 传参时的顺序,以数组的方式返回结果(不是按响应的时间顺序返回结果)
- 新建 promise.js
console.log('start');
const p1 = (() => {
return new Promise((resolve, reject) => {
console.log("p1");
const status = true;
if (status) {
setTimeout(() => {
resolve("p1:成功");
}, 1000);
} else {
setTimeout(() => {
reject("p1:失败");
}, 1000);
}
});
})();
const p2 = new Promise((resolve, reject) => {
console.log('p2');
const status = true;
if (status) {
setTimeout(() => {
resolve("p2:成功");
}, 3000);
} else {
setTimeout(() => {
reject("p2:失败");
}, 1000);
}
});
const p3 = new Promise((resolve, reject) => {
console.log('p3');
const status = true;
if (status) {
setTimeout(() => {
resolve("p3:成功");
}, 2000);
} else {
setTimeout(() => {
reject("p3:失败");
}, 2000);
}
});
Promise.all([p1, p2, p3])
.then((res) => {
console.log('res',res);
})
.catch((err) => {
console.log('err',err);
});
- 终端执行
node promise.js
- 结果
// 立即打印
start
p1
p2
p3
// 3s 后
res [ 'p1:成功', 'p2:成功', 'p3:成功' ]
4. 等所有 promise 异步执行完毕统一返回结果,Promise.allSettled([p1,p2,p3])
- Promise.allSettled() 接受一个由promise对象组成的数组:如果传入函数返回的promise对象,需要传入函数立即执行后的结果
- 特点:解决 Promise.all 短路问题
- 获取结果:此方法解决了 Promise.all() 短路的问题,不管是 resolve 还是 reject,都会按照 [fn1,fn2,fn3] 传参时的顺序,以数组的方式将状态和数据放入对象中统一返回
- 新建 promise.js
console.log('start');
const p1 = (() => {
return new Promise((resolve, reject) => {
console.log("p1");
const status = true;
if (status) {
setTimeout(() => {
resolve("p1:成功");
}, 1000);
} else {
setTimeout(() => {
reject("p1:失败");
}, 1000);
}
});
})();
const p2 = new Promise((resolve, reject) => {
console.log('p2');
const status = true;
if (status) {
setTimeout(() => {
resolve("p2:成功");
}, 3000);
} else {
setTimeout(() => {
reject("p2:失败");
}, 1000);
}
});
const p3 = new Promise((resolve, reject) => {
console.log('p3');
const status = false;
if (status) {
setTimeout(() => {
resolve("p3:成功");
}, 2000);
} else {
setTimeout(() => {
reject("p3:失败");
}, 2000);
}
});
Promise.allSettled([p1, p2, p3])
.then((res) => {
console.log('res',res);
})
.catch((err) => {
console.log('err',err);
});
- 终端执行
node promise.js
- 结果
// 立即打印
start
p1
p2
p3
// 3s 后
res [
{ status: 'fulfilled', value: 'p1:成功' },
{ status: 'fulfilled', value: 'p2:成功' },
{ status: 'rejected', reason: 'p3:失败' }
]
5. 不等所有 promise 异步执行完毕,只是返回响应最快的 promise 结果,Promise.race([p1,p2,p3])
- Promise.race() 接受一个由promise对象组成的数组:如果传入函数返回的promise对象,需要传入函数立即执行后的结果
- 获取结果:不管是 resolve 还是 reject,只是返回响应最快的 promise 结果
- 新建 promise.js
console.log('start');
const p1 = (() => {
return new Promise((resolve, reject) => {
console.log("p1");
const status = true;
if (status) {
setTimeout(() => {
resolve("p1:成功");
}, 1000);
} else {
setTimeout(() => {
reject("p1:失败");
}, 1000);
}
});
})();
const p2 = new Promise((resolve, reject) => {
console.log('p2');
const status = true;
if (status) {
setTimeout(() => {
resolve("p2:成功");
}, 3000);
} else {
setTimeout(() => {
reject("p2:失败");
}, 1000);
}
});
const p3 = new Promise((resolve, reject) => {
console.log('p3');
const status = false;
if (status) {
setTimeout(() => {
resolve("p3:成功");
}, 2000);
} else {
setTimeout(() => {
reject("p3:失败");
}, 2000);
}
});
Promise.race([p1, p2, p3])
.then((res) => {
console.log('res',res);
})
.catch((err) => {
console.log('err',err);
});
- 终端执行
node promise.js
- 结果
// 立即打印
start
p1
p2
p3
// 3s 后
res p1:成功