前言
- 本文如标题,回顾三个知识点
- 判断是不是Promise
- js抛出错误的类型
- 手写Promise.all
判断是不是Promise
方式一 Object.prototype.toString.call
代码如下:
// p存在,且对象原型上是Promise
function isPromise(p) {
return p && Object.prototype.toString.call(p) === "[object Promise]";
}
方式二 Promise有.then方法,以此为依据
代码如下:
// 有值,且值是对象或函数,在一个也要有.then的函数方法
function isPromise(val) {
return (
val &&
(typeof val === 'object' || typeof val === 'function') &&
typeof val.then === 'function'
);
}
二者对比
- 方式二比方式一更为精准强大(推荐)
- 对于规范化的Promise(就是JavaScript自带的Promise)
- 二者判断检测结果能力都一样
- 但是对于一些特定的Promise可能不太准确
- 比如:特定库的Promise(Tiny Promise)、或者自己继承Promise去操作什么的,可能不太够用
- 不过正常来说也够用了
js如何抛出错误?
- 在js中抛错是通过throw语句,进一步来说,又可以分为:
- 直接抛
- 进阶抛
直接抛错误
throw语句后面抛什么都行,比如:
// 抛出各种数据类型
throw '报错了'
throw 404
throw false
throw null
throw undefined
throw {}
throw () => {}
throw []
一般来说,抛出字符串比较多一些,不会抛出各种其他的数据类型
进阶抛错误
- 如果想要进一步明确错误的类型
- 可以使用js自带的Error相关构造函数
- 一般常见的有4个如下:
// 常见的4种进阶错误区分
throw new Error('普通错误') // 抛出普通错误(用的多一些)
throw new SyntaxError('语法错误') // 抛出语法错误
throw new ReferenceError('引用错误') // 抛出引用错误
throw new RangeError('范围错误') // 抛出范围错误
工作中我们根据具体的情况和需求,选择合适的方式来抛出错误能处理异常更加“优雅”
手写一个Promise.all
复制粘贴即用,注释代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.0/axios.js"></script>
</head>
<body>
<script>
// 判断是不是Promise
function isPromise(p) {
return p && Object.prototype.toString.call(p) === "[object Promise]";
}
function myPromiseAll(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
throw new TypeError('接收的必须是数组,不是数组抛错');
}
if (promises.length === 0) {
throw new Error('接收的数组不能为空,空数组也抛错');
}
// Promise.all接收数组,最终也返回数组,result存起来用于返回
const result = [];
// 已经完成的数量,初始为0
let doneNum = 0;
// 数组循环执行
promises.forEach((promise, index) => {
if (!isPromise(promise)) { throw new TypeError('接收的数组中的每一项都必须要是Promise') }
promise
.then((val) => {
result[index] = val; // 顺序存值
// result.push(val); // 非顺序存值
doneNum = doneNum + 1; // 已完成数量+1
if (doneNum === promises.length) { resolve(result) } // 任务全部完成,resolve出去
})
.catch((err) => {
// 只要有一个Promise失败,立刻拒绝返回Promise
reject(err);
})
});
});
}
const p1 = function () {
return new Promise(async (resolve, reject) => {
let res = await axios.get('http://ashuai.work/api/getIdName?id=1')
resolve(res)
})
}
const p2 = function () {
return new Promise(async (resolve, reject) => {
let res = await axios.get('http://ashuai.work/api/getIdName?id=2')
resolve(res)
})
}
const p3 = function () {
return new Promise(async (resolve, reject) => {
let res = await axios.get('http://ashuai.work/api/getIdName?id=3')
resolve(res)
})
}
myPromiseAll([p1(), p2(), p3()])
.then((values) => { console.log(values) })
.catch((error) => { console.error(error) })
</script>
</body>
</html>
手写Promise... 未完待续...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。