将同步调用转成异步调用?
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(\'准备开始....\');
以上是关于将同步调用转成异步调用?的主要内容,如果未能解决你的问题,请参考以下文章