Promise的使用
使用promise的目的:就是为了解决我们的回调地狱的问题,这个也是我们的一种方案来实现基本的异步编程的解决方案
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>发送ajax请求</button>
<script>
let button = document.querySelector("button");
button.addEventListener("click", function(){
let xhr = new XMLHttpRequest();
xhr.open("get",'http://172.20.3.242/cqupt/#/login', true)
xhr.send(null);
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 || xhr.status < 300){
console.log(JSON.parse(xhr.responseText))
}
}
}
})
</script>
</body>
</html>
Promise的状态
promise实现就是一个基本的异步编程的实现
一般的话,实现promise的时候,我们实现的我们的那个:let promise_name = new Promise(callback)
使用promise就是为了实现基本的一些更好的控制我们的异步的操作
promise 是具有三个状态的:
1.pending 进行中
2.fulfilled 已成功
3.rejected 已失败
const p1 = new Promise((resolve, reject)=>{
resolve("ok")
reject("error")
});
console.log(p1)
Promise 状态确定后的 then的方法
首先我们通过我们传入的参数:resolve 和 reject 来实现确定我们的最后的状态
resolve ==> fulfilled状态
reject ==> rejected状态
promise实例化对象后面含有三中方法:then / catch / finally
const p1 = new Promise((resolve, reject)=>{
reject("error")
})
console.log(p1)
console.dir(Promise)
const result = p1.then(value=>{
console.log(value)
}, reason=>{
console.log(reason)
})
console.log(result)
result.then(value => {}, reason => {})
Promise then方法的链式调用
const p1 = new Promise((resolve, reject)=>{
resolve("ok fulfilled")
})
p1.then(value => {
console.log(value)
console.log("第一次链式调用")
}).then(value => {
console.log(value)
console.log("第二次链式调用")
return new Promise((resolve, reject) => {
reject("error rejected")
})
}).then(value => {
console.log(value)
console.log("第三次链式调用")
})
Promise then方法的链式读取文件
const fs = require("fs")
const p1 = new Promise((resolve, reject) => {
fs.readFile("./01.txt", (err, data) => {
if(err){
reject(err)
console.log(err)
}else{
resolve(data)
console.log(data)
}
})
}).then(value=>{
return new Promise((resolve, reject) =>{
fs.readFile("./01.txt", (err, data)=>{
if(err){
reject([data, err])
}else{
resolve([value, data])
}
})
})
}, reason=>{})
const fs = require("fs");
function ReadFileFunc(path){
return new Promise((resolve, reject)=>{
fs.readfile(path, (err, data)=>{
if(err){
reject(err)
}else{
resolve(data)
}
})
}).then(value=>{
console.log(value.toString());
})
}
Promise.all 方法的使用
const p1 = new Promise((resolve, reject)=>{
resolve("ok")
})
const p2 = new Promise((resolve, reject)=>{
resolve("ok")
})
const p3 = new Promise((resolve, reject)=>{
resolve("ok")
})
let result = Promise.all([p1, p2, p3])
console.log(result)
function getUserList(method, url, content){
return new Promise((resolve, reject)=>{
let xhr = new XMLHttpRequest()
xhr.open(method, url,true);
if(content){
xhr.send(content)
}else{
xhr.send(null)
}
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
try{
const result = JSON.parse(xhr.responseText)
resolve(result)
}catch(error){
reject(error)
}
}else{
reject(new Error(`network is not ok ${xhr.statusText}` ))
}
}
}
})
}
function ReadData(){
return new Promise((resolve, reject)=>{
setInterval(function(){
resolve("成功读取数据")
}, 1000)
})
}
function ReadText(){
return new Promise((resolve, reject)=>{
setInterval(function(){
resolve("成功读取文章")
}, 2000)
})
}
function ReadBanner(){
return new Promise((resolve, reject)=>{
setInterval(function(){
resolve("成功读取Banner")
}, 3000)
})
}
let result = Promise.all(ReadData(), ReadText(), ReadBanner())
Promise allSettled方法
这个方法就是实现判断我们的最后的那个是否执行完
function getUserList(method, url, content){
return new Promise((resolve, reject)=>{
let xhr = new XMLHttpRequest()
xhr.open(method, url,true);
if(content){
xhr.send(content)
}else{
xhr.send(null)
}
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300){
try{
const result = JSON.parse(xhr.responseText)
resolve(result)
}catch(error){
reject(error)
}
}else{
reject(new Error(`network is not ok ${xhr.statusText}` ))
}
}
}
})
}
Promise.allSeettled([getUserList("get", "sdbcidc"), getUserList("get", "cvdscfsd")]).then(value=>{
let successList = value.filter(item => item.status === "fulfilled");
console.log(successList)
}).catch(error=>{
console.log(error)
})
Promise.any 方法
只要有一个promise是成功的,那么最后的就是成功的
只要传入的参数Promise的状态一个是fulfilled ,那么最后的状态就是fulfilled
const p1 = new Promise((resolve, reject)=>{
resolve("ok")
})
const p2 = new Promise((resolve, reject)=>{
resolve("ok")
})
const p3 = new Promise((resolve, reject)=>{
reject("error")
})
let result = Promise.any([p1, p2, p3])
console.log(result)
Promise.race() 方法
就是谁先获得状态,那么就先实现使用那个的状态
const p1 = new Promise((resolve, reject)=>{
resolve("1")
})
const p2 = new Promise((resolve, reject)=>{
resolve("2")
})
const p3 = new Promise((resolve, reject)=>{
reject("3")
})
let result = Promise.any([p1, p2, p3])
console.log(result)
Promise.reject() 和 Promise.resolve()
Promise.reject()始种实现的是我们的那个拒绝的状态
resolve:如果里面的参数是一个那个非promise对象,那么就是我们的fulfilled
如果是我们的那个promise对象,那么最后的状态就是取决于后面的那个promise状态
Promise.catch方法
catch是主要用来指定我们的失败的时候的回调函数,返回的是一个promise实例化对象
const p1 = new Promise((resolve, reject)=>{
reject("error")
})
p1.then(value=>{
console.log(value)
}).catch(error=>{
console.log(error)
})
Promise.finally方法
就是实现的基本的我们的不管最后的状态如何,我们都实现运行下面的结果
Promise终止链条
就是子啊我们的Promise语句中使用我们的最后的那个: return new Promise(()=>{})
终止promise链条的实质上就是就是返回一个pending状态的Promise对象
promise的状态只有三种: pending / fulfilled / rejected
实现修改我们的promise的状态的方法:
1.通过resolve来实现
2.通过reject来实现
3.通过throw来实现
使用promise的时候,我们先确定状态还是先确定回调函数
1.如果说是实现的同步状态,那么线确定状态,在确定回调
2.如果说是一个异步实现,那么就是先确定回调,在确定状态
这个的话就是通过的我们的判断状态后实现的回调函数,先确定状态在执行
async函数
const p1 = new Promise((resolve, reject)=>{
})
async function func(){
return new Promise((resolve, reject) => {
})
}
func();
func().then(value=>{}, reason=>{}).then.....
await表达式
async function func(){
let re = await new Promise(() => {})
}
宏任务和微任务
如果说我们的含有那个同步任务和微任务和宏任务
那么就是先执行我们的同步任务,然后执行我们的微任务,最后执行的才是我们的宏任务
同 微 宏任务
宏任务:dom事件回调、ajax事件回调、定时器回调
微任务:promise回调 、 mutation回调
然后我们的那个任务的话: heap堆区/ stack栈区==》 就是我们的浏览器的主线程的任务
宏任务和微任务就是我们的浏览器执行的分线程的任务
setTimeout(()=>{
console.log(1111)
},0)
new Promise((resolve, reject)=>{
resolve()
console.log(2222)
}).then(value=>{
console.log(3333)
})
console.log(4444)
Promise 源码的手写
// html文件中的script中的方法
/*
1.首先我们的promise是一个那个构造函数,作用是为了实现基本的创键实例化对象
语法:let 变量名 = new 构造函数名(); 在堆内存中实现开辟一个空间,分配其大小以及设置其地址值
在我们的堆内存中主要实现的存储我们的引用数据类型
在我们的栈内存中主要实现存储的是我们的基本数据类型和地址值
2.promise是具有一个那个参数的,分为我们的实际参数,其中的参数是一个回调函数(执行器函数 executor)
3.执行器函数executor里面也是需要实现接收两个参数的: resolve , reject
4.任何一个构造函数上都是含有默认的属性: prototype
同时我们的Promise的实例化对象是含有两个属性的: PromiseState(实现记录的是我们的最后的一个Promise的状态值)
PromiseResult(实现记录的是我们的Promise的结果值)
5.通过我们的调用resolve方法可以实现我们Promise的状态实现pending -> fulfilled
通过基本的那个reject + throw的方法,可以实现将promise的状态: pending -> rejected
6.executor执行器函数是含有两个形式参数的,一个是resolve和reject
7.resolve和reject又是回调函数
方法一:
let self = this
实现修改函数中的this指向方法:call apply bind
函数名.call(新的this指向,实际参数1, 实际参数2...)
函数名.apply(新的this指向,实际参数1, 实际参数2...)
call/apply函数只要一修改完我们的this的指向后,就实现立即执行
bind的话,不会实现立即执行,而且函数是具有那个返回值的
返回值是和我们的原本的数据结构是一模一样的的修改完函数的this指向的新函数
8.注意我们的Promise的状态的话,只可以实现修改一次,一旦确定了就不可以实现改变了
这个时候就需要我们实现一个判断
9.原型链的实现:我们需要注意的就是我们使用的时候,那个对象的prototype方法和实例化对象的__proto__指向的是相同的
都是指向的一个空对象,我们是可以通过这一点来实现我们的那个创建我们的使用的方法的,这样可以实现节省我们的内存空间
然后我们使用的 Object.assign() 就是我们的对象间的合并的方法,将源对象的属性复制到目标对象中,返回目标对象
Object.assign(target, ...sources)
target:目标对象
sources:源对象
返回值是target
我们使用这个方法是为了实现最基本的那个在Promise的原型上实现添加then等等的方法
10.注意我们的promise对象的关键是我们的异步执行和链式调用
实现异步操作的话,我们就要实现异步操作的话,就要使用那个定时器
链式调用的思路:就是实现我们的那个:后面的链式调用的话,是取决于我们的那个前者到底是失败还是成功
这个时候我们就要使用新的那个promise对象
在我们的then方法中还是具有三种情况的:就是数据是一个那个promise对象和不是promise对象,以及是否是我们的那个抛出异常
*/
// 1.创建一个promise的实例化对象
let p1 = new Promise((resolve, reject)=>{
// console.log("我是一个promise执行器函数")
/*
首先我们的原生中的含有的改变状态的方法是我们的那个:
resolve("成功时候的描述信息")
reject("失败的时候的描述信息")
throw "异常信息"
*/
})
console.log(p1)
p1.then(value=>{}, reason=>{})
function Promise() {
}
window.Promise = Promise;
(function(window){
function Promise(executor){
this.PromiseState = "pending"
this.PromiseResult = undefined
const _resolve = value => {
if(this.PromiseState !== "pending") return;
this.PromiseState = "fulfilled"
this.PromiseResult = value
}
const _reject = value => {
if(this.PromiseState !== "pending") return;
this.PromiseState = "rejected"
this.PromiseResult = value
}
try{
executor(_resolve, _reject);
}catch(error){
if(this.PromiseState !== "pending") return;
this.PromiseState = "rejected"
this.PromiseResult = error || error.message
}
}
Object.assign(Promise.prototype, {
then(onfulfilled, onrejected){
return new Promise((resolve, reject) => {
if(this.PromiseState === "fulfilled") {
setTimeout(() => {
try{
const value = onfulfilled(this.PromiseResult)
if(value instanceof Promise){
value.then(resolve, reject)
}else{
reject(value)
}
}catch(e){
reject(err)
}
})
}else if(this.PromiseState === "rejected"){
setTimeout(() => {
try{
const value = onrejected(this.PromiseResult)
if(value instanceof Promise){
value.then(resolve, reject)
}else{
resolve(value)
}
}catch(err){
reject(err)
}
})
}
})
},
})
Window.Promise = Promise;
})(Window);