将同步调用转成异步调用?

Posted leaf930814

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将同步调用转成异步调用?相关的知识,希望对你有一定的参考价值。

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

来看个栗子:

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(\'准备开始....\'); 

  

以上是关于将同步调用转成异步调用?的主要内容,如果未能解决你的问题,请参考以下文章

同步调用异步 Javascript 函数

从片段中调用分离的异步任务类

异步 Mongoose 调用

调用fastdfsapi是同步的还是异步的

如何从同步代码 Python 中调用异步函数

同步调用与异步调用