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

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

来看个栗子:

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

  

时间: 2024-10-10 13:33:12

将同步调用转成异步调用?的相关文章

客户端的异步调用

C#客户端的异步操作 阅读目录 开始 示例项目介绍 同步调用服务 异步接口介绍 1. 委托异步调用 2. 使用IAsyncResult接口实现异步调用 3. 基于事件的异步调用模式 4. 创建新线程的异步方式 5. 使用线程池的异步方式 6. 使用BackgroundWorker实现异步调用 客户端的其它代码 各种异步方式的优缺点 异步文件I/O操作 数据库的异步操作 异步设计的使用总结 在Asp.net中使用异步 上篇博客[用Asp.net写自己的服务框架] 我讲述了如何实现自己的服务框架,但

C#同步和异步调用

这篇文章仅当总结之用,参考了很多前辈们的文章,加上了点点自己的理解 C#的同步和异步线程是依靠委托来完成,主要需要用到委托的Invoke方法,BeginInvoke和EndInvoke方法 所谓同步线就是阻塞当前线程来完成调用的方法,然后才继续调用当前线程的后面的操作,实际上都是在同一个线程中执行,效率不高.需要用到Invoke方法 异步线程不阻塞当前线程,而是把需要调用的方法加入线程池中,来同步执行,即同一时间两个及其以上的线程共同都在执行,效率很高.需要用到BeginInvoke和EndIn

[SAP ABAP开发技术总结]Function远程、同步、异步调用

目录导航 声明:原创作品,转载时请注明文章来自SAP师太博客,并以超链接形式标明文章原始出处,否则将追究法律责任!原文出自: 20.1.         Function调用... 233 20.1.1.     更新FM:LUW.. 233 20.1.2.     RFC函数:远程调用... 234 20.1.2.1.           同步... 234 20.1.2.2.           异步... 234 20.1.2.2.1.       事务性RFC调用... 234 20.1

python 37 同步、异步调用

目录 1. 阻塞与非阻塞 2. 同步与异步 2.1 异步调用 2.2 同步调用 2.3 异步调用回收的第一种方式 3. 异步调用+回调函数 3.1 requests模块 3.2 异步调用回收的第二种方式 1. 阻塞与非阻塞 执行的角度: ? 阻塞:阻塞调用是指调用结果返回之前,当前线程会被挂起(如遇到io操作).函数只有在得到结果之后才会将阻塞的线程激活. ? 非阻塞:程序没有遇到IO阻塞,或者程序遇到IO,通过某种方式,让CPU强行运行程序. 2. 同步与异步 发布的角度: ? 同步调用:在发

161107、spring异步调用,完美解决!

项目中,用户抢单,下单需要向对方推送消息,但是加上推送就会造成抢单和下单性能降低,反应变慢,因为抢单下单动作跟推送部分是同步的,现在想改成异步推送. 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring 3.x之后,就已经内置了@Async来完美解决这个问题,本文将完成介绍@Async的用法. 异步调用 在解释异步调用之前,我们先来看同步调用的定义:同步就是整个处

C#基础之异步调用实例教程

本文实例形式展示了C#中异步调用的实现方法,并对其原理进行了较为深入的分析,现以教程的方式分享给大家供大家参考之用.具体如下: 首先我们来看一个简单的例子: 小明在烧水,等水烧开以后,将开水灌入热水瓶,然后开始整理家务 小文在烧水,在烧水的过程中整理家务,等水烧开以后,放下手中的家务活,将开水灌入热水瓶,然后继续整理家务 这也是日常生活中很常见的情形,小文的办事效率明显要高于小明.从C#程序执行的角度考虑,小明使用的同步处理方式,而小文则使用的异步处理方式. 同步处理方式下,事务是按顺序一件一件

AsyncCallback BeginInvode endinvode 异步调用

下面是搜藏的代码: //首先准备好,要进行C#异步调用的方法(能C#异步调用的,最好不多线程) private string MethodName(int Num, out int Num2) { Num2 = Num; return "HelloWorld"; } //程序终点 //C#异步调用完成时,执行的方法(回调方法), //此方法只能有IAsyncResult一个参数,但是该参数几乎万能,可以传递object private void CallBackMethod(IAsyn

cglib实现全配置的异步调用

参考cglib资料:http://www.tuicool.com/articles/IVfANr 实现逻辑为,对service类用cglib包装,让其调用方法改成异步调用,Future.线程池 对service方法的返回对象也用cglib包装,使其带有LazyLoad的功能 主要点:对cglib需要处理的类信息缓存,提高效率,通过lazyload,让用户不需要修改自己的代码,通过配置的方式就能进行异步化调用方法

.Net组件程序设计之异步调用

.Net组件程序设计之异步调用 说到异步调用,在脑海中首先想到就是BeginInvoke(),在一些常用对象中我们也会常常见到Invoke()和BeginInvoke(), 要想让自己的组件可以被客户端调用或者是异步调用,这样的设计是合理的,这也是组件异步机制当中的一条 (说句题外话--其实大多数知识都隐藏在我们平时经常见到的对象或者是代码里,只不过是没有去细心的发现) 在.NET中首先就会想到使用委托来进行异步调用,关于委托的定义在 委托与事件一文中已经大概的说过了,文中只是对委托进行了 大概