Promise 必须为以下三种状态之一:等待态(Pending)、执行态(Fulfilled)和拒绝态(Rejected)。一旦Promise 被 resolve 或 reject,不能再迁移至其他任何状态(即状态 immutable)
文章目录
前言
Promise构造函数接受一个函数作为参数
resolve 将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),
reject 将Promise对象的状态从“未完成”变为“失敗”(即从Pending变为Rejected),
then方法可以接受两个回调函数作为参数 ,第一个回调函数是Promise对象的状态变为Resolved时调用,第二个回调函数是Promise对象的状态变为 Reject时调用,第二参数可选,这两个函数都接受Promise对象传出的值作为参数
一、Promise是什么?
Promise 是异步的解决方案,也是异步编程的选择
Promise使用步骤
1.实例化Promise
代码如下(示例):
function func(data) {
return new Promise((resolve, reject) => {
data ? resolve(data) : reject({ msg: "Promise失敗的", data });
});
}
2.then方法
then方法是定义在原型对象Promise.prototype上的 Promise实例添加状态改变时的回调函数
func()
.then(
(data) => {
console.log(data, 1);
},
(err) => {
console.log(err, 2);
}
)
.catch((err) => {
console.log(err, 1);
});
3.链式操作
var p1 = new Promise((resolve, reject) => {
resolve(1);
});
var p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(p1);
}, 1000);
});
then方法返回的是一个新的Promise实例
p2(1)
.then(
(data) => {
console.log("resolve", data);
},
(err) => {
console.log("p2的错误对象", err);
}
)
.then((d) => {
console.log(d);
});
3.链式操作返回值
let p1 = new Promise((resolve, reject) => {
resolve(886);
})
p1.then(data=>{
return data+4; //886+4
}).then(data2=>{
console.log(data2); // 889
})
p1 返回为886第一个then拿到数据后在本身数据加了4并返回出去,在第二个the 拿到的值为 886+4 为889
拒绝处理也可以使用上面操作返回值
let p1 = new Promise((resolve, reject) => {
reject(886);
})
p1.catch(data=>{
return data+4; //886+4
}).catch(data2=>{
console.log(data2); // 889
})
Promise 返回 Promise
let p1 = new Promise((resolve, reject) => {
resolve(66);
});
let p2 = new Promise((resolve, reject) => {
resolve(88);
});
p1.then((result) => {
console.log(result);
return p2;
}).then((data) => {
console.log(data);
})
.catch((err) => {});
p1 返回的是成功的 在then 可以得到 66 的返回值 因为then 函数 可以链式操作,所有这里返回的是 p2 (但是这个p2 是成功的状态 这里可以直接把p2看着88 前提必须在then 函数里面,后面并且还有then来接收上一个then的返回的值)
如果p2 是一个reject的 则触发catch 函数
拆分上面的 p1 和p2
let p1 = new Promise((resolve, reject) => {
resolve(66);
});
let p2 = new Promise((resolve, reject) => {
resolve(88);
});
let p3 = p1.then((data) => {
console.log(data);//66
return p2;
});
p3.then((data) => {
console.log(data); //88
});
这里有一个明显的一点是 p2 完成是p3 这个变量来接收的 p2的返回值,而p3这个时候就可以使用then因为p2返回的是一个Promise
如果 p2 是拒绝处理的,并且又没有去处理这个错误 分别在NodeJS 和浏览器都会抛出异常
浏览器中
unhandledrejection 事件循环中
rejectionhandled 在一个事件循环后
NodeJS中触发
unhandledRejection 事件循环中触发
rejectionHandled 在一个事件循环后
let p1 = new Promise((resolve, reject) => {
resolve(66);
});
let p2 = new Promise((resolve, reject) => {
reject(88);
});
p1.then((result) => {
console.log(result);
return p2;
}).then((data) => {
console.log(data);
});
错误在Node环境出现以下错误
(node:17384)
UnhandledPromiseRejectionWarning: 88
(Use node --trace-warnings ...
to show where the warning was created)
(node:17384) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict
(see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:17384) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
错误在浏览器中错误
Uncaught (in promise) 88
没有解决的错误处理都有一个特点 都是可以看见是 88 这个reject抛出来的错误
Promise 并发 all ,race,allSettled,any
Promise.all()
必须所有的成功才会成功 一个失败所有都会失败
let p1 = new Promise((resolve, reject) => {
resolve(66);
});
let p2 = new Promise((resolve, reject) => {
resolve(77);
});
let p3 = new Promise((resolve, reject) => {
resolve(88);
});
let p4 = new Promise((resolve, reject) => {
resolve(99);
});
let all = Promise.all([p1, p2, p3, p4]);
all.then((data) => {
console.log(data); // [ 66, 77, 88, 99 ]
});
Promise.all() 返回的是数组 并且是数组里面是resolve的值
一个Promise拒绝处理,后面所有都拒绝处理
let p1 = new Promise((resolve, reject) => {
resolve(66);
});
let p2 = new Promise((resolve, reject) => {
resolve(77);
});
let p3 = new Promise((resolve, reject) => {
resolve(88);
});
let p4 = new Promise((resolve, reject) => {
reject(99);
});
let all = Promise.all([p1, p2, p3, p4]);
all
.then((data) => {
console.log(data);
})
.catch((err) => {
console.log(err); //99
});
Promise.race()
Promise.race()跟Promise.all() 相似,但是不同的是会
let p1 = new Promise((resolve, reject) => {
resolve(66);
});
let p2 = new Promise((resolve, reject) => {
resolve(77);
});
let p3 = new Promise((resolve, reject) => {
resolve(88);
});
let all = Promise.race([p1, p2, p3]);
all
.then((data) => {
console.log(data); // 66
})
.catch((err) => {
console.log(err);
});
使用setTimeout测试
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(66);
}, 3);
});
let p3 = new Promise((resolve, reject) => {
//setTimeout 第3个参数是传递到 第一个参数(函数)的形参
setTimeout( (data) => {
resolve(data);
}, 2,88);
});
let all = Promise.race([p1, p3]);
all
.then((data) => {
console.log(data); // 88
})
.catch((err) => {
console.log(err);
});
同样的是如果其中有没有被处理(reject触发)都会没有值
Promise.allSettled()
该方法接收一个数组,并且数组里面是Promise待执行,该方法跟all 差不多,区别再去,会等待里面所有Promise 有结果才会响应,并且返回的是数组,
方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果
let p1 = new Promise((resolve, reject) => {
resolve(66);
});
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(77);
}, 2000);
});
let p3 = new Promise((resolve, reject) => {
reject(88);
});
let p4 = new Promise((resolve, reject) => {
throw new Error('故意的')
});
let all = Promise.allSettled([p1, p2, p3, p4]);
all.then((data) => {
console.log(data);
}).catch((err) => {
console.log(err);
});
浏览器中
NodeJS中
这里可以看出来,是返回的数组并且是可以迭代的数组,分别有二个状态 fulfilledy和 rejected
如果 Promise 直接抛出出错,rejected 则有 data[3].reason.message 这个错误描述 如果错误被reject返回出来状态则为rejected 错误描述为item.reason
all.then((data) => {
data.forEach(item => {
item.status === 'fulfilled' && console.log(item.status, item.value);
item.status === 'rejected' && console.log(item.status, item.reason.message || item.reason);
})
}).catch((err) => {
console.log(err);
});
Promise.any
当我们只需要一个 promise 成功,而不关心是哪一个成功时此方法很有用的
any知道ts的,any 为任意,这里的any 标识其中一个成功则成功
方法用于返回第一个成功的 promise 。只要有一个 promise 成功此方法就会终止,它不会等待其他的 promise 全部完成。
不像 Promise.all() ,会等待所以的执行完后才会返回一组完成值
也不像 Promise.race() 总是返回第一个结果值(resolved/reject)那样,这个方法返回的是第一个 成功的 值。这个方法将会忽略掉所有被拒绝的 promise,直到第一个 promise 成功
const pErr = new Promise((resolve, reject) => {
reject("总是失败");
});
const pSlow = new Promise((resolve, reject) => {
setTimeout(resolve, 500, "最终完成");
});
const pFast = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "很快完成");
});
Promise.any([pErr, pSlow, pFast]).then((value) => {
console.log(value);
})
如果一个都没有成功则触发异常
const pErr = new Promise((resolve, reject) => {
reject("失败");
});
const pSlow = new Promise((resolve, reject) => {
setTimeout(reject, 500, "最终完成");
});
const pFast = new Promise((resolve, reject) => {
setTimeout(reject, 100, "很快完成");
});
Promise.any([pErr, pSlow, pFast]).then((value) => {
console.log(value);
}).catch(err=>{
console.error(err); // All promises were rejected
})
Promise继承
class newPromise extends Promise {
success(resolve, reject) {
return this.then(resolve, reject);
}
failure(reject) {
return this.catch(reject);
}
}
const newP = new newPromise((resolve, reject) => {
reject(199);
resolve(99);
});
newP.success((data) => {
console.log(data);
})
.failure((err) => {
console.error(err); //199
});
console.log(newP); //newPromise [Promise] { 99 }
我们自定义了一个newPromise的类,并且继承Promise,newPromise上扩展了二个方法success,以及failure,success模仿了 then函数 ,failure模仿了catch函数,因为是继承过来的Promise,所有我们能够在newPromise 这个类里面使用 Promise 所有东西,使用this 就能访问原有Promise所有的方法
extends 可以继承任何比如说 Array 数组的操作,可以自定义扩展方法
4.全局的错误处理
Nodejs错误处理
在Node.js 中处理Promise拒绝时会触发 process对象到二个是件
1.unhandlerejection 在一个时间循环中,当Promise 被拒绝,并且没有提供错误处理方法,就会触发该事件
- unhandledrejection 继承自 PromiseRejectionEvent,而 PromiseRejectionEvent 又继承自 Event。因此unhandledrejection 含有 PromiseRejectionEvent 和 Event 的属性和方法。
设计这些事件是用来识别那些被拒绝却又没有被处理的Promise
下面演示一下 unhandledRejection
let Rejected;
process.on("unhandledRejection", (reason, promise) => {
console.log("=====", reason.message);
console.log("0000..", promise);
});
Rejected = Promise.reject(new Error("手写BUG"));
下面演示一下 rejectionHandled
let Rejected;
process.on("rejectionHandled", (reason, promise) => {
console.log(Rejected === promise);
});
Rejected = Promise.reject(new Error("手写BUG"));
setTimeout(() => {
Rejected.catch((val) => {
console.log(" Rejected.catch", val.message);
});
}, 2000);
这里 rejectionHandled 事件在拒绝处理程序最后被调用触发,如果在rejected 直接添加错误处理程序,那么rejectionHandled 就不会触发 因为 rejected创建的过程与错误处理程序的调用在一个事件循环中,此时rejectionHandled事件尚未生效
收集Node中的Promise错误没有被处理的函数
const EventPollingPromiseError = (hadeleRejection:Function)=>{
let poccibyUnhandledRejection = new Map();
process.on("unhandledRejection", (reason, promise) => {
poccibyUnhandledRejection.set(reason, promise);
});
process.on("rejectionHandled", (promise) => {
poccibyUnhandledRejection.delete(promise);
});
setInterval(() => {
poccibyUnhandledRejection.forEach((reason, promise) => {
console.log(reason.message ? reason.message : reason);
hadeleRejection(promise,reason)
});
poccibyUnhandledRejection.clear();
}, 6000);
};
浏览器错误处理
unhandledrejection 在一个事件循环中 当Promise被拒绝,并没有提供错误处理的时候触发
rejectionhandled 在一个事件循环后,当Promise被拒绝 若拒绝处理被调用,就触发该事件
在Nodejs 中 事件处理程序接收多个独立的参数,在浏览器中事件处理程序接受以下属性的事件对象作为参数,
事件名 | 描述 |
---|---|
type | 事件名称(onunhandledrejection或者,onrejectionhandled ) |
promise | 被拒绝的Promise |
reason | 来自Peomise拒绝的值 |
浏览器实现的另一处不同的是,在二个事件中都可以使用拒绝值 reason
let Rejected;
window.onunhandledrejection = (event) => {
console.log(event);
console.log(event.reason);
console.log(event.reason);
console.log(Rejected === event);
};
window.onrejectionhandled = (event) => {
console.log(event);
};
Rejected = Promise.reject(new Error("手写BUG"));
收集浏览器中Promise错误没有被处理的函数
const browserEventTopPromiseError = (hadeleRejection:Function)=>{
let poccibyunhandledRejection = new Map();
window.onunhandledrejection = (event:any) => {
poccibyunhandledRejection.set(event.promise, event.reason);
};
window.onrejectionhandled = (event:any) => {
poccibyunhandledRejection.delete(event.promise);
};
setInterval(() => {
poccibyunhandledRejection.forEach((reason, promise) => {
console.log(reason.message ? reason.message : reason);
hadeleRejection(promise,reason)
});
poccibyunhandledRejection.clear();
}, 6000);
}
该处使用的url网络请求的数据。
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。