首页 > 代码库 > 将同步调用转成异步调用?
将同步调用转成异步调用?
有时候同步调用和异步调用同时存在的时候,难免出现混乱。
来看个栗子:
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(‘准备开始....‘);
将同步调用转成异步调用?
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。