【手写Promise】
一、JS的错误1、错误的类型2、错误处理3、错误对象<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content
·
一、JS的错误
1、错误的类型
2、错误处理
3、错误对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
//1、错误类型
// ReferenceError:引用的变量不存在
// TypeError:数据类型不正确,b.xxx错误在b
// RangeError:数据值不在允许范围内
// SyntaxError:语法错误
//2、错误处理
//捕获错误:try...catch
//抛出错误:throw error
//3、错误对象
// message:错误相关信息
// stack属性:函数调用栈记录信息
//本身知道异常是什么,不需要自己定义异常
try {
let d;
console.log(d.xxx);
//从前面接到error
} catch (error){
console.log(error.message);
console.log(error.stack);
}
//不知道异常如何抛出,需要自己定义异常
function time(){
if(Date.now()%2 ==1){
console.log('奇数时间没问题');
}else{
throw new Error('偶数时间有问题')
}
}
try {
time()
} catch (error) {
console.log(error.message);
}
</script>
</body>
</html>
二、Promise介绍
JS中进行异步编程的新的解决方案;
语法上是一个构造函数,功能上是一个对象来封装异步操作并可以获得结果。
1、promise状态pending
promise状态只能改变一次,只有一个结果数据
pending----->resolved::成功数据value
pending----->rejected::失败原因reason
2、Promise基本使用
先同步任务----- new promise实例对象—启动异步任务----返回promise对象-----给promise对象绑定回调函数------甚至可以在异步之后再绑定回调
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
const p = new Promise((resolve,rejecte)=>{ //执行器函数先执行(同步任务),再new Promise(),启动异步任务
//异步函数
setTimeout(() => {
if(Date.now()%2 == 0){
resolve('成功') //value
}else{
rejecte('失败') //reason
}
}, 1000);
})
p.then(
//onResolve
//此处的value是从异步函数中获取到的成功的返回值
(value)=>{
console.log(value);
},
//onRejected
//此处的reason是从异步函数中获取到的失败的原因
(reason)=>{
console.log(reason);
}
)
</script>
</body>
</html>
3、新旧区别--------解决回调地狱
旧的:必须在启动异步任务之前指定好成功、失败的回调
新的:可以启动异步任务,甚至结束异步任务后,再指定回调
三、深度使用Promise
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
new Promise((resolve,reject)=>{
setTimeout(() => {
// resolve('成功回调');
reject('失败的回调')
}, 1000);
}).then(
(value) =>{
console.log(value);
}
).catch(
(reason)=>{
console.log(reason);
}
)
//产生一个值为1的成功的promise
const p1 = Promise.resolve(1);
p1.then(
value =>{
console.log(value);
}
)
//产生一个值为2的失败的promise
const p2 = Promise.reject(2);
p2.catch(
reason =>{
console.log(reason);
}
)
// Promise.all必须所有的都有成功的回调,返回的是成功的数据,才算成功;如果失败需要返回失败的原因
const pAll = Promise.all([p1,p2,p3])
// Promise.race看谁先完成,会返回第一个成功的和第一个失败的
const pRace = Promise.race();
</script>
</body>
</html>
几个问题:
1、多个then,可以全部执行,
2、先有回调函数 .the,但是状态没改,保存好;后改变状态(并且指定数据),调用函数
先改变状态(并且指定数据),调用函数;;后有回调函数 .the,并异步调用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
new Promise((resolve,reject)=>{
resolve('成功回调')
}).then(
//异步执行
value =>{
console.log(value);
},
reason =>{
console.log(reason);
}
);
console.log('--------');
// --------
// 成功回调
console.log('--------');
//.then之后是一个新的Promise,根据新Promise的状态,来判断之后的.then
new Promise((resolve,reject)=>{
resolve('成功回调')
}).then(
//异步执行
value =>{
console.log('onResolved1',value); //onResolved1,成功回调
return 2 //此时会返回2
return Promise.resolve(3); //返回3
throw 4; //传递给下面的onRejected2
},
reason =>{
console.log('onResolved2',reason);
}
).then(
//异步执行
value =>{
console.log('onResolved2',value); //undefined //2
},
reason =>{
console.log('onRejected2',reason);
}
);
</script>
</body>
</html>
异常穿透和中断Promise链
//层层穿透
Promise.then.then.catch
//中断Promise链
return new Promise(()=>{})
四、自定义Promise,手写
/*
自定义Promise函数模块:IIFE
*/
(function(window){
//Promise构造函数
//executor执行器函数
function Promise(executor){
//执行器函数,会立即执行
function resolve(){
}
function reject() {
}
//传入的参数为两个函数
executor(resolve,reject)
}
/*
//.then接收成功失败的回调
返回新的Promise
*/
Promise.prototype.then = function(onResolved,onRejected){
}
/*
接收失败的回调
返回新的promise
*/
Promise.prototype.catch = function(onRejected){
}
/*
promise函数对象的resolve方法
*/
Promise.resolve = function(value){
}
/*
promise函数对象的reject方法
*/
Promise.reject = function(reason){
}
//all接收数组
Promise.all = function(promises){
}
//race接收数组
Promise.race = function(promise){
}
})(window)
五、async和await的使用
1、async函数:返回值是promise对象,结果由返回值决定
2、await表达式:右侧一般是promise对象,也可为其它;若为promise,则返回成功值,
3、await必须写在async的函数中,async函数可以无await;如果await的promise失败,用try catch来抛出异常
六、JS异步之宏队列与微队列
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 3,4,0,1,2
//执行函数队列又分为宏与微,每执行新的一个宏之前,都要去微里面看看是否还有函数
setTimeout(() => {
console.log(0);
Promise.resolve(1).then(value =>{
console.log(value);
})
}, 1000);
setTimeout(() => {
console.log(2);
}, 1000);
Promise.resolve(3).then(value=>{
console.log(value);
})
Promise.resolve(4).then(value =>{
console.log(value);
})
</script>
</body>
</html>
七、手写promise(函数)
/*
自定义Promise函数模块:IIFE
*/
(function(window){
const PENDING = 'pending';
const RESOVLED = 'resolved';
const REJECTED = 'rejected';
//Promise构造函数
//executor执行器函数
function Promise(executor){
let that = this;
this.status = PENDING; //状态未变之前都是pending
this.data = undefined; //未定义的数据
this.callbacks = []; //每个元素的结构:onResolved(){},onRejected(){}
//执行器函数,会立即执行
//两个改变promise状态的函数
function resolve(value){
if(that.status!==PENDING) return
//调用resolve后,需要将状态改变成为resolved
that.status = RESOVLED;
//保存data数据
that.data= value;
//如果有未执行的callback,则立即异步执行onResolved,是包含两个回调的对象
if(that.callbacks.length>0){
setTimeout(() => {
that.callbacks.forEach(element => {
element.onResolved(value)
});
});
}
}
function reject(reason) {
if(that.status!==PENDING) return
//调用reject后,需要将状态改变成为rejected
that.status = REJECTED;
//保存data数据
that.data= reason;
//如果有未执行的callback,则立即异步执行onRejected,是包含两个回调的对象
if(that.callbacks.length>0){
setTimeout(() => {
that.callbacks.forEach(element => {
element.onResolved(reason)
});
});
}
}
//传入的参数为两个函数
//除了resolve和reject,还有可能自己抛出异常,会失败,此时需要一个try catch
try {
executor(resolve,reject)
} catch (error) {
reject(error);
}
}
/*
//.then接收成功失败的回调
返回新的Promise
*/
Promise.prototype.then = function(onResolved,onRejected){
const that = this;
// 指定回调函数的默认值(必须是函数)
onResolved = typeof onResolved === 'function'?onResolved:value =>value //继续向下传递
onRejected = typeof onRejected ==='function'? onRejected:reason =>{throw reason} //抛出异常
return new Promise((resolve,reject) =>{
function handle(callback){
try {
const result = onResolved(that.data)
if(result instanceof Promise){
result.then(resolve,reject
// value =>{
// resolve(value)
// },
// reason=>{
// reject(reason)
// }
)
}
} catch (error) {
reject(error);
}
}
if(this.status ===PENDING){
//假设当前状态还是pending,将回调保存下来
this.callbacks.push({
onResolved(value){
handle(onResolved)
},
onRejected(reason){
handle(onRejected)
}
})
}else if(this.status ===RESOVLED){
setTimeout(() => {
// 如果回调是promise,return的promise结果就是这个promise结果
handle(onResolved)
});
}else{
//如果前面的promise返回的是失败的回调
setTimeout(() => {
handle(onRejected)
});
}
})
}
/*
接收失败的回调
返回新的promise
*/
Promise.prototype.catch = function(onRejected){
return this.then(undefined,onRejected)
}
/*
promise函数对象的resolve方法
*/
Promise.resolve = function(value){
return new Promise((resolve,reject) =>{
if(value instanceof Promise){
value.then(resolve,reject)
}else{
resolve(value);
}
})
}
/*
promise函数对象的reject方法
*/
Promise.reject = function(reason){
return new Promise((resolve,reject) =>{
reject(reason)
})
}
//all接收数组
Promise.all = function(promises){
const values = [];
const resolvedCount = 0;
return new Promise((resolve,reject)=>{
//遍历promise获取每个promise的结果
promises.forEach((p,index) =>{
Promise.resolve(p).then(
//成功的时候需要放入数组中
value => {
resolvedCount++;
values[index] = value;
if(resolvedCount == promises.length){
resolve(values);
}
},
reason =>{
//只要一个失败了,return的promise就失败
reject(reason)
}
)
})
})
}
//race接收数组
Promise.race = function(promise){
//返回一个pomise
return new Promise((resolve,reject) =>{
Promise.resolve(p).then(
//一旦有成功,return成功
value =>{
resolve(value);
},
//一旦有失败,return失败
reason =>{
reject(reason)
}
)
})
}
// promise的resolveDelay,rejectDelay
/* promise函数对象的resolveDelay方法
*/
Promise.resolveDelay = function(value,time){
return new Promise((resolve,reject) =>{
setTimeout(() => {
if(value instanceof Promise){
value.then(resolve,reject)
}else{
resolve(value);
}
}, time);
})
}
/*
promise函数对象的rejectDelay方法
*/
Promise.rejectDelay = function(reason,time){
return new Promise((resolve,reject) =>{
setTimeout(() => {
reject(reason)
}, time);
})
}
})(window)
手写promise(类)
/*
自定义Promise函数模块:IIFE
*/
(function(window){
const PENDING = 'pending';
const RESOVLED = 'resolved';
const REJECTED = 'rejected';
class Promise {
constructor(executor){
let that = this;
this.status = PENDING; //状态未变之前都是pending
this.data = undefined; //未定义的数据
this.callbacks = []; //每个元素的结构:onResolved(){},onRejected(){}
//执行器函数,会立即执行
//两个改变promise状态的函数
function resolve(value){
if(that.status!==PENDING) return
//调用resolve后,需要将状态改变成为resolved
that.status = RESOVLED;
//保存data数据
that.data= value;
//如果有未执行的callback,则立即异步执行onResolved,是包含两个回调的对象
if(that.callbacks.length>0){
setTimeout(() => {
that.callbacks.forEach(element => {
element.onResolved(value)
});
});
}
}
function reject(reason) {
if(that.status!==PENDING) return
//调用reject后,需要将状态改变成为rejected
that.status = REJECTED;
//保存data数据
that.data= reason;
//如果有未执行的callback,则立即异步执行onRejected,是包含两个回调的对象
if(that.callbacks.length>0){
setTimeout(() => {
that.callbacks.forEach(element => {
element.onResolved(reason)
});
});
}
}
//传入的参数为两个函数
//除了resolve和reject,还有可能自己抛出异常,会失败,此时需要一个try catch
try {
executor(resolve,reject)
} catch (error) {
reject(error);
}
}
/*
//.then接收成功失败的回调
返回新的Promise
*/
then (onResolved,onRejected){
const that = this;
// 指定回调函数的默认值(必须是函数)
onResolved = typeof onResolved === 'function'?onResolved:value =>value //继续向下传递
onRejected = typeof onRejected ==='function'? onRejected:reason =>{throw reason} //抛出异常
return new Promise((resolve,reject) =>{
if(this.status ===PENDING){
//假设当前状态还是pending,将回调保存下来
this.callbacks.push({
onResolved(value){
onResolved(that.data);
try {
const result = onResolved(that.data)
if(result instanceof Promise){
result.then(resolve,reject
// value =>{
// resolve(value)
// },
// reason=>{
// reject(reason)
// }
)
}
} catch (error) {
resolve(error);
}
},
onRejected(reason){
onRejected(that.data);
try {
const result = onRejected(that.data)
if(result instanceof Promise){
result.then(resolve,reject
// value =>{
// resolve(value)
// },
// reason=>{
// reject(reason)
// }
)
}
} catch (error) {
reject(error);
}
}
})
}else if(this.status ===RESOVLED){
setTimeout(() => {
// 如果回调是promise,return的promise结果就是这个promise结果
try {
const result = onResolved(that.data)
if(result instanceof Promise){
result.then(resolve,reject
// value =>{
// resolve(value)
// },
// reason=>{
// reject(reason)
// }
)
}else{//返回的不是promise,返回promise为成功,value就是返回值
resolve(result)
}
} catch (error) {
reject(error);
}
});
}else{
//如果前面的promise返回的是失败的回调
setTimeout(() => {
// 如果回调是promise,return的promise结果就是这个promise结果
try {
const result = onRejected(that.data)
if(result instanceof Promise){
result.then(resolve,reject
// value =>{
// resolve(value)
// },
// reason=>{
// reject(reason)
// }
)
}
} catch (error) {
try {
const result = onResolved(that.data)
if(result instanceof Promise){
result.then(resolve,reject
// value =>{
// resolve(value)
// },
// reason=>{
// reject(reason)
// }
)
}
} catch (error) {
reject(error);
}
}
});
}
})
}
/*
接收失败的回调
返回新的promise
*/
catch (onRejected){
return this.then(undefined,onRejected)
}
/*
promise函数对象的resolve方法
*/
static resolve(value){
return new Promise((resolve,reject) =>{
if(value instanceof Promise){
value.then(resolve,reject)
}else{
resolve(value);
}
})
}
/*
promise函数对象的reject方法
*/
static reject(reason){
return new Promise((resolve,reject) =>{
reject(reason)
})
}
//all接收数组
static all(promises){
const values = [];
const resolvedCount = 0;
return new Promise((resolve,reject)=>{
//遍历promise获取每个promise的结果
promises.forEach((p,index) =>{
Promise.resolve(p).then(
//成功的时候需要放入数组中
value => {
resolvedCount++;
values[index] = value;
if(resolvedCount == promises.length){
resolve(values);
}
},
reason =>{
//只要一个失败了,return的promise就失败
reject(reason)
}
)
})
})
}
//race接收数组
static race (promise){
//返回一个pomise
return new Promise((resolve,reject) =>{
Promise.resolve(p).then(
//一旦有成功,return成功
value =>{
resolve(value);
},
//一旦有失败,return失败
reason =>{
reject(reason)
}
)
})
}
// promise的resolveDelay,rejectDelay
/* promise函数对象的resolveDelay方法
*/
static resolveDelay (value,time){
return new Promise((resolve,reject) =>{
setTimeout(() => {
if(value instanceof Promise){
value.then(resolve,reject)
}else{
resolve(value);
}
}, time);
})
}
/*
promise函数对象的rejectDelay方法
*/
static rejectDelay (reason,time){
return new Promise((resolve,reject) =>{
setTimeout(() => {
reject(reason)
}, time);
})
}
}})(window)
更多推荐
已为社区贡献1条内容
所有评论(0)