本文参加了由公众号@若川视野发起的每周源码共读活动, 点击了解详情一起参与。
本文已参与「新人创作礼」活动,一起开启掘金创作之路
前言
🤔加油读源码!!!!!
知识点
- Math.floor()
返回小于或等于一个给定数字的最大整数。 - Math.random()
返回0-1之间的一个浮点数,这个浮点数小于1 - AbortController
AbortController接口表示一个对象,允许您根据需要中止一个或多个 Web 请求,文档地址:developer.mozilla.org/zh-CN/docs/… - addEventListener()
注册监听事件
type(即事件类型,常见的如click, DomContentLoaded, error等)
listener listener既可以是function,也可以是一个带有handleEvent方法的object对象
options
capture(指定事件行为是否为捕获事件,默认为false,即冒泡)
once(指定事件是否只执行一次,默认为false,当为true时,只执行一次后,事件会自动被移除)
passive 默认为false,当指定为true时,如果事件本身执行了preventDefault方法,用户代理将不会做任何事情,取而代之的是生成一个控制台warning
- removeEventListener()
移除监听事件
源码
1.简单的延迟执行方法
const delay1 = (ms) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, ms);
});
}
await delay1(1000);
console.log('输出这句'); //一秒后打印这一句
2.可以传参数的延迟函数
const delay2 = (ms, { value } = {}) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(value);
}, ms);
});
}
const result = await delay2(1000, { value: '哈哈哈' });
console.log('输出结果', result); //一秒后打印 哈哈哈
3.可以控制延迟是否执行成功或者失败
增加参数willResolve 为true则执行成功 false则会执行reject
const delay3 = (ms, { value, willResolve } = {}) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (willResolve) {
resolve(value);
}
else {
reject(value);
}
}, ms);
});
}
try {
const result = await delay3(1000, { value: '哈哈', willResolve: false });
console.log('永远不会输出这句');
}
catch (err) {
console.log('输出结果', err); //打印 哈哈
}
4.增加随机时间返回结果方法
增加了randomInteger随机时间计算函数,该函数返回一个数字,这个就是多少秒后执行
const randomInteger = (minimum, maximum) => {
// console.log((Math.random() * (maximum - minimum + 1)) + minimum)
return Math.floor((Math.random() * (maximum - minimum + 1)) + minimum)
};
const createDelay = ({ willResolve }) => (ms, { value } = {}) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (willResolve) {
resolve(value);
}
else {
reject(value);
}
console.log(ms, 'ms')
}, ms);
});
}
const createWithTimers = () => {
const delay = createDelay({ willResolve: true }); //返回成功的延迟函数
delay.reject = createDelay({ willResolve: false }); //返回失败的延迟函数
delay.range = (minimum, maximum, options) => delay(randomInteger(minimum, maximum), options); //随机时间返回成功
console.log(delay, 'delay')
return delay;
}
const delay4 = createWithTimers();
5.清楚延时,提前执行,在返回的promise实例中增加clear函数 此函数负责清楚延时器 再去
const randomInteger = (minimum, maximum) => Math.floor((Math.random() * (maximum - minimum + 1)) + minimum);
const createDelay = ({ willResolve }) => (ms, { value } = {}) => {
let timeoutId;
let settle;
const delayPromise = new Promise((resolve, reject) => {
settle = () => {
if (willResolve) {
resolve(value);
}
else {
reject(value);
}
}
timeoutId = setTimeout(settle, ms);
});
//在promise返回的实例中
delayPromise.clear = () => {
clearTimeout(timeoutId);
timeoutId = null;
settle(); //此处为啥要在去调用一个settle的原因是,如果不调用 Promise的状态会一直为pedding状态
};
console.log(delayPromise, 'delayPromise')
return delayPromise;
}
const createWithTimers = () => {
const delay = createDelay({ willResolve: true });
delay.reject = createDelay({ willResolve: false });
delay.range = (minimum, maximum, options) => delay(randomInteger(minimum, maximum), options);
return delay;
}
const delay5 = createWithTimers();
const delayedPromise = delay5(1000, { value: '哈哈哈' });
setTimeout(() => {
delayedPromise.clear();
}, 300);
// 300 milliseconds later
console.log(await delayedPromise);
//=> '哈哈哈'
6.取消执行延迟函数
使用了AbortController插件
const randomInteger = (minimum, maximum) => Math.floor((Math.random() * (maximum - minimum + 1)) + minimum);
const createAbortError = () => {
const error = new Error('Delay aborted');
error.name = 'AbortError';
return error;
};
const createDelay = ({ willResolve }) => (ms, { value, signal } = {}) => {
//判断是否传入AbortController 实例返回对象的signal 如果aborted中止状态为true则返回失败提示信息
if (signal && signal.aborted) {
return Promise.reject(createAbortError());
}
let timeoutId;
let settle;
let rejectFn;
//创建中止监听的的方法
const signalListener = () => {
clearTimeout(timeoutId);
rejectFn(createAbortError());
}
//移除监听的事件
const cleanup = () => {
if (signal) {
signal.removeEventListener('abort', signalListener);
}
};
const delayPromise = new Promise((resolve, reject) => {
settle = () => {
cleanup();
if (willResolve) {
resolve(value);
} else {
reject(value);
}
};
rejectFn = reject;
timeoutId = setTimeout(settle, ms);
});
//判断是否又signal 是则添加监听事件abort
if (signal) {
signal.addEventListener('abort', signalListener, { once: true });
}
delayPromise.clear = () => {
clearTimeout(timeoutId);
timeoutId = null;
settle();
};
return delayPromise;
}
const createWithTimers = () => {
const delay = createDelay({ willResolve: true });
delay.reject = createDelay({ willResolve: false });
delay.range = (minimum, maximum, options) => delay(randomInteger(minimum, maximum), options);
return delay;
}
const delay6 = createWithTimers();
const abortController = new AbortController();
setTimeout(() => {
abortController.abort(); //调用中止监听的方法
}, 500);
try {
await delay6(1000, { signal: abortController.signal });
} catch (error) {
// 500 milliseconds later
console.log(error.name)
//=> 'AbortError'
}
End
这期源码让我知道了AbortController插件齐基本就是利用addEventListener添加监听事件然后触发事件执行addEventListener中的函数,清除延时,返回错误信息。