zoukankan      html  css  js  c++  java
  • 将同步调用转成异步调用?

    有时候同步调用和异步调用同时存在的时候,难免出现混乱。

    来看个栗子:

    function loadReady(callback){
    	var readyState = document.readyState;
    	if(readyState ==='complete'||readyState==='interactive'){
    		typeof callback === 'function' && callback();
    	}else{
    		window.addEventListener('DOMContentLoaded', callback);
    	}
    }
    
    loadReady(function(){
    	console.log('DOM已经加载解析完成了!');
    });
    
    console.log('准备开始....'); 
    

     结果:

     

    这不是我们想要的,我们希望是先打印“准备开始....”,可是事与愿违。
    上面的执行结果是因为回调函数被提前执行了,换句话说,回调函数被当成同步函数执行了。

    怎么修改一下执行流程呢?
    可以这么修改:

    function loadReady(callback){
    	var readyState = document.readyState;
    	if(readyState ==='complete'||readyState==='interactive'){
    		typeof callback === 'function' && setTimeout(callback, 0);
    	}else{
    		window.addEventListener('DOMContentLoaded', callback);
    	}
    }
    
    loadReady(function(){
    	console.log('DOM已经加载解析完成了!');
    });
    
    console.log('准备开始....'); 
    

      

    修改之后的代码中,callback被当做setTimeout的回调函数执行了,setTimeout的第二个参数虽然是0,但是却是在任务消息队列中等待执行的,具体可以看《JS运行机制之 Event Loop 的思考》。

         所以,有时为了避免混乱,适当把回调函数的同步调用转成异步调用是很有必要的,其实就不应该对异步回调函数进行同步调用。对于这个问题,可以看Effective JavaScript 详细介绍---


    1、绝对不能对异步回调函数(即使在数据已经就绪)进行同步调用。
    2、如果对异步回调函数进行同步调用的话,处理顺序可能会与预期不符,可能带来意料之外的后果。
    3、对异步回调函数进行同步调用,还可能导致栈溢出或异常处理错乱等问题。
    4、如果想在将来某时刻调用异步回调函数的话,可以使用 setTimeout 等异步API。”

    看看promise的调用方式
    为了避免同步调用和异步调用引起的混乱,promise规定promise只能使用异步的调用方式。

    看看promise改写上面的代码:

    function onReadyPromise() {
        return new Promise(function (resolve, reject) {
            var readyState = document.readyState;
            if (readyState === 'interactive' || readyState === 'complete') {
                resolve();
            } else {
                window.addEventListener('DOMContentLoaded', resolve);
            }
        });
    }
    onReadyPromise().then(function () {
        console.log('DOM已经加载解析完成了!');  //异步,执行了resolve()之后就异步的执行.then()里面的回调函数
    });
    console.log('准备开始....'); 
    

      

  • 相关阅读:
    解决html中 在不同浏览器中占位大小不统一的问题 SUperman
    解决C#调用执行js报检索 COM 类工厂中 CLSID 为 {0E59F1D51FBE11D08FF200A0D10038BC} 组件失败
    面向对象程序设计_tesk1_寒假伊始
    面对对象程序设计_task2_1001.A+B Format (20)
    面向对象程序设计_Task5_Calculator1.5.0
    面向对象程序设计_Task4_Calculator1.1
    面向对象程序设计_课堂作业_01_Circle
    面向对象程序设计__Task3_Calculator
    面对对象程序设计_task2_C++视频教程
    pkgconfig 简述
  • 原文地址:https://www.cnblogs.com/leaf930814/p/6829824.html
Copyright © 2011-2022 走看看