我有两个异步函数,每个函数都有其setInterval
回调。
第一个:
timer = null;
r = 0;
async function t() {
// return timer
if (timer) return(timer);
timer = setInterval(() => {
r += 10
if (r === 100) clearInterval(timer);
console.log('timer', timer, 'r', r)
}, 1000)
}
console.time('timer')
console.log(await t())
console.timeEnd('timer')
第二个:
timer1 = null;
r1 = 0;
async function t1() {
// clearInterval timer1
if (timer1) clearInterval(timer1);
timer1 = setInterval(() => {
r1 += 10
if (r1 === 100) clearInterval(timer1);
console.log('timer1', timer1, 'r1', r1)
}, 1000)
}
console.time('timer1')
console.log(await t1())
console.timeEnd('timer1')
但是当我运行它们时,它们做了相同的事情,输出如下:
timer 18 r 10
timer 18 r 20
timer 18 r 30
timer 18 r 40
timer 18 r 50
timer 18 r 60
timer 18 r 70
timer 18 r 80
timer 18 r 90
timer 18 r 100
第二个输出与上面相同:
timer1 23 r1 10
timer1 23 r1 20
timer1 23 r1 30
timer1 23 r1 40
timer1 23 r1 50
timer1 23 r1 60
timer1 23 r1 70
timer1 23 r1 80
timer1 23 r1 90
timer1 23 r1 100
我的问题:
return (timer)
,第二个是clearInterval(timer)
,但是第一个不会在每个间隔中返回timerId,而第二个则不会clearInterval(timerId)
它应该在每个间隔中生成一个新的timerId,对吗?为什么?我对以上问题感到困惑。
非常感谢。
我是这个工具的新生,但如果您能理解我的意思,那太好了,并且做得很好!
import React from 'react';
import PropTypes from 'prop-types';
function loadScript(url) {
const script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
document.body.appendChild(script);
return new Promise((resolve) => {
if (script.readyState) { // IE
script.onreadystatechange = function change() {
if (script.readyState === 'loaded' || script.readyState === 'complete') {
resolve();
}
};
} else { // Others
script.onload = function load() {
resolve();
};
}
});
}
export default class LazyloadMap extends React.Component {
static propTypes = {
loading: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), // loading effects
url: PropTypes.string, // SDK url
onload: PropTypes.func, // load success
onfail: PropTypes.func, // load failed
}
static defaultProps = {
loading: 'Map was in loading', // string | ReactNode
url: 'http://api.map.baidu.com/api?v=2.0&ak=***************************&callback=initializeBMap',
onload: () => {},
onfail: (e) => { alert(`加载地图失败,请重试: ${e};`); },
}
static timer = null;
static record = 0;
static initialized() {
const timeout = 1e4;
return new Promise((resolve, reject) => {
if (
window.BMap &&
typeof window.BMap === 'object' &&
!('apiLoad' in window.BMap)
) {
resolve(window.BMap);
} else {
// if timer has been initialized, does create a new `timer`
// and clear it. Another way is just return the old `timer`,
// i have tried the diff ways, but i am very confusing with that
// so i sent this post, any one can help me? thanks in advanced.
if (LazyloadMap.timer) {
clearInterval(LazyloadMap.timer);
}
LazyloadMap.timer = setInterval(() => {
LazyloadMap.record += 10;
if (
window.BMap &&
typeof window.BMap === 'object' &&
!('apiLoad' in window.BMap)
) {
resolve(window.BMap);
clearInterval(LazyloadMap.timer);
}
if (LazyloadMap.record >= timeout) {
clearInterval(LazyloadMap.timer);
reject(new Error('加载超时, 请重试'));
}
}, 10);
}
});
}
state = {
loaded: false
}
async componentWillMount() {
const { url, onload, onfail } = this.props;
const onLoadSuccess = () => {
this.setState({
loaded: true,
}, () => {
onload && onload(window.BMap);
});
};
if (!window.BMap) {
try {
console.time('componentWillMount:await-load-Bmap-used');
await loadScript(url);
await LazyloadMap.initialized();
console.timeEnd('componentWillMount:await-load-Bmap-used');
onLoadSuccess(window.BMap);
} catch (e) {
onfail && onfail(e instanceof Error ? e : new Error(e));
}
} else {
onLoadSuccess(window.BMap);
}
}
render() {
return this.state.loaded ? this.props.children : this.props.loading;
}
}
// flag to records whether BMap SDK was initialized,
// if it did BMap will be an object
window.BMap = undefined;
// after loadScript(url) server does return `BMap` SDK, it returned following JavaScript code
// so i use a `timer` to listening `loaded` attribute
/* (function () {
window.BMap_loadScriptTime = (new Date).getTime();
window.BMap = window.BMap || {};
window.BMap.apiLoad = function () {
delete window.BMap.apiLoad;
if (typeof initializeBMap == "function") {
initializeBMap()
}
};
var s = document.createElement('script');
s.src = 'http://api.map.baidu.com/getscript?v=2.0&ak=**********************&services=&t=20180629105706';
document.body.appendChild(s);
})(); */
window.initializeBMap = LazyloadMap.initialized;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://unpkg.com/prop-types@15.6/prop-types.js"></script>