JavaScript中“ async / await”中的“ return timer”和“ clearInterval(timer)”之间有什么区别?

时间:2018-07-12 13:00:51

标签: javascript async-await frontend settimeout setinterval

我有两个异步函数,每个函数都有其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

我的问题:

  1. 他们做了同样的事情吗?有什么区别?
  2. 很显然,我在每个函数中做了不同的事情,第一个是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>

0 个答案:

没有答案