同步和阻塞:这两个术语可以互换使用,指的是代码的执行会在函数返回之前停止。如果某个操作阻塞,那么脚本就无法继续,这意味着必须等待。
异步和非阻塞:这两个术语可以互换使用,指的是基于回调的、允许脚本并行执行操作的方法。脚本无需等待某个操作的结果才能继续前进,因为操作结果会在事件发生时由回调来处理。使用异步方法,操作无需一个接一个地发生(自己注:就是并行了)。
@1 同步和阻塞的例子:
function sleep(milliseconds) {
var start = new Date().getTime();
while ((new Date().getTime() - start) < milliseconds){ }
}
function fetchPage() {
console.log('fetching page');
sleep(2000); // simulate time to query a database
console.log('data returned from requesting page');
}
function fetchApi() {
console.log('fetching api');
sleep(2000); // simulate time to fetch from an api
console.log('data returned from the api');
}
fetchPage();
fetchApi();
@2 异步和非阻塞方式的例子:
$(function () {
$('p').hide(5000, function() {
alert("The paragraph is now hidden");
});
console.log("测试");
});
@3 常用的同步回调
function haveBreakfast(food, drink, callback) {
console.log('Having breakfast of ' + food + ', ' + drink);
if (callback && typeof(callback) === "function") {
sleep(2000);
callback();
}
}
function sleep(milliseconds) {
var start = new Date().getTime();
while ((new Date().getTime() - start) < milliseconds){ }
}
haveBreakfast('toast', 'coffee', function() {
console.log('Finished breakfast. Time to go to work!');
});
console.log("如果是回调的话,Finished会在这个之后显示");//结果是最后显示
首先说下,什么是回调:
回调指的是将一个函数作为参数传递给另一个函数,并且通常在第一个函数完成后被调用。
在JavaScript中,函数可以作为参数传递到另一个函数中,然后被调用。这个突然让我想起了C#的"委托",只是将方法传递给另一个函数进行执行,当然在学委托时,还是感觉很牛叉的。@3是同步的回调函数,无可厚非,console.log需要等待上面脚本执行。
@3并不是node.js中说的回调函数。node.js是异步、非阻塞的,回调的意义在于函数调用后执行, 且下面的脚本无需等待某个操作的结果才能继续下去。回调常用于处理的函数的操作结果。
接下来就说下我们以前接触到的回调。
相信大家都使用过jQuery,我们在jQuery中经常使用回调,最常见的就是Ajax(异步的)中的success:function(data){…代码…},调试过这段代码的都知道,Ajax后面的脚本可以在success回调之前执行。在@2中也是如此,console.log()会在动画完成之前执行,不必等待。
如果了解xmlhttprequest异步的话,会知道它有四个状态来判断是否请求完成。想象下Ajax的过程,前台向后台请求数据,后台会返回状态给前台,当状态为成功时,会去调用success中的函数。简单的说,获得数据,通知前台,前台调用success函数。当然别忘了,Ajax是异步的,请求可以是多个!至于多个请求响应的先后顺序、前台的回调挂哪,成功后怎么调回调等,咱们不关心,重点是知道回调这个概念! 至于具体实现的,此处不关心。
如果将jQuery的Ajax进行假设,假设它只许成功、请求需要的路径等都是已知的。这时我们可以抽象为jQuery.Ajax({data:'data'},function(success){…代码…}),此时和动画进行简单修改jQuery.hide('slow', function(success) {…代码…}),然后进行类比,会发现它们有一些共通点:
第一:只需要参数就能进行函数的调用,回调并不是必须的。 jQuery.Ajax只需要data参数就能进行请求;jQuery.hide只需要知道时间(speed),就能进行动画操作。
第二:都是调用函数执行完后,后续操作交由回调函数执行的(匿名)。
第三:不阻塞后面的代码。
理解此处对于node的匿名函数有帮助。
Node.js到处使用回调(异步调用回调),尤其在有I/O操作发生的地方。Node.js运行在单一的进程中,并且要求开发人员使用异步编程风格。
那么Node.js是怎么实现异步的编程风格呢?我们写的代码是异步的吗?
Node.js使用JavaScript的事件循环来支持它所推崇的异步编程风格。事件循环使得循环可以将回调先保存起来,而后当事件在将来发生时再运行。也就是说,回调是Node.js实现编程的关键方法,因为回调让代码在其他事件发生的时候运行。Node.js的设计旨在处理网络中数据流的不确定性,促成这样的设计是JavaScript的事件循环和对回调的使用,这使得程序员可以编写对网络或I/O事件进行响应的异步代码。这也就是说编写的代码一般都是异步的。(jQuery绑定事件都有都有回调吧?)。
Node.js一些特点:
Node的关键思想是,将代码围绕着事件来架构,而不是按照期待中的输入顺序来架构。
Node的核心哲学是在事件循环和单一进程的上下文中尝试并编程。
Node.js进程在还有已经注册的回调尚未触发之前将不会退出。
Node.js将事件循环用于到服务器端的编程上,尤其是在网络和I/O操作的上下文中,Node.js经常被当成是一个网络编程框架,因为它的设计旨在处理网络中数据流的不确定性。
Node.js所不适合的地方包括处理大量数据或者长时间运行计算等。Node.js旨在网络中推送数据并瞬间完成。
在使用回调的时候可能会遇到哪些问题?
在使用回调时可能碰到与控制流相关的问题。在这里需要指定回调的执行顺序。可能发现回调的嵌套深度会多达4到5层,嵌套过多可能会碰到深度嵌套的回调和控制流的问题。
附:请求对象和事件循环


- 初步揭秘node.js中的事件
当你学习node.js的时候,Events是一个非常重要的需要理解的事情.非常多的Node对象触发事件,你能在文档API中找到很多例子.但是关于如何写自己的事件和监听,你可能还不太清楚.如果你不了解, ...
- Node.js权威指南 (10) - Node.js中的错误处理与断言处理
10.1 使用domain模块处理错误 / 272 10.1.1 domain模块概述 / 272 10.1.2 创建并使用Domain对象 / 274 10.1.3 隐式绑定与显式绑定 / 276 ...
- node.js如何使用回调
Node.js到处使用回调,尤其在有I/O(输入/输出)操作的地方. 下面是在一个Node.js中使用filesystem模块中从磁盘上读入文件内容示例一: var fs = require('fs' ...
- node.js中process进程的概念和child_process子进程模块的使用
进程,你可以把它理解成一个正在运行的程序.node.js中每个应用程序都是进程类的实例对象. node.js中有一个 process 全局对象,通过它我们可以获取,运行该程序的用户,环境变量等信息. ...
- node.js中通过dgram数据报模块创建UDP服务器和客户端
node.js中 dgram 模块提供了udp数据包的socket实现,可以方便的创建udp服务器和客户端. 一.创建UDP服务器和客户端 服务端: const dgram = require('dg ...
- node.js中net网络模块TCP服务端与客户端的使用
node.js中net模块为我们提供了TCP服务器和客户端通信的各种接口. 一.创建服务器并监听端口 const net = require('net'); //创建一个tcp服务 //参数一表示创建 ...
- node.js中stream流中可读流和可写流的使用
node.js中的流 stream 是处理流式数据的抽象接口.node.js 提供了很多流对象,像http中的request和response,和 process.stdout 都是流的实例. 流可以 ...
- node.js中fs文件系统模块的使用
node.js中为我们提供了fs文件系统模块,实现对文件或目录的创建,修改和删除等操作. fs模块中,所有的方法分为同步和异步两种实现. 有 sync 后缀的方法为同步方法,没有 sync 后缀的方法 ...
- 在Node.js中操作文件系统(一)
在Node.js中操作文件系统 在Node.js中,使用fs模块来实现所有有关文件及目录的创建,写入及删除操作.在fs模块中,所有对文件及目录的操作都可以使用同步与异步这两种方法.比如在执行读文件操作 ...
随机推荐
- Lyft Level 5 Challenge 2018 - Final Round (Open Div. 2) C. The Tower is Going Home(思维+双指针)
https://codeforces.com/contest/1075/problem/C 题意 一个宽为1e9*1e9的矩阵中的左下角,放置一个车(车可以移动到同一行或同一列),放置一些墙,竖的占据 ...
- Vue + Element UI 实现权限管理系统
Vue + Element UI 实现权限管理系统 前端篇(一):搭建开发环境 https://www.cnblogs.com/xifengxiaoma/p/9533018.html
- Oracle中根据当前时间和活动类型去数据库查询活动id
活动类型默认是1,代表邀请好友 select * from t_invite_activityinfo twhere sysdate >= t.begintime and sysdate< ...
- Mybatis-Plus 实战完整学习笔记(六)------select测试一
查询方法(3.0.3) 1.查询一个员工的数据 @Test public void selectMethod() throws SQLException { // 根据ID获取一个对象的数据 Empl ...
- MarkDown总结
转载自:https://www.jianshu.com/p/q81RER:做了一些部分修改: 一:总纲 1.所有的格式均要空格,如#后面加个空格,-后面加空格,1.后面加空格等等: 2.双向包裹的不能 ...
- Effective C++ 随笔(2)
条款5 了解c++默默编写并调用哪些函数 编译器自动生成的copy 构造函数,copy赋值操作符,析构函数,构造函数,这些都是public和inline的,此处inline的意思是他们的定义都是在头文 ...
- C#的math类的全部运算方法
Abs 返回指定数字的绝对值.Acos 返回余弦值为指定数字的角度.Asin 返回正弦值为指定数字的角度.Atan 返回正切值为指定数字的角度.Atan2 返回正切值为两个指定数字的商的角度.BigM ...
- 恢复VS2010/VS2013项目为VS2008项目
https://blogs.msdn.microsoft.com/rextang/2009/07/06/convert-vs2010-projects-back-to-vs2008-ones/ 摘抄如 ...
- uva1659(最大费用循环流)
紫书上的一道题,做法见紫书P378,这篇博客用的第二种方法,关于正确性的证明,画图可以发现如果一个环是负环,跑最小费用流跑出的是环上的所有正边,再减去负边和即为跑一遍的负权,如果是正环,最小费用流即为 ...
- quartz之hello(java)
quartz 任务调度框架 简单的说:就是在特定的时间,干指定的事件,然后具体到某个对象去做 quartz初之体验: 1.pom.xml文件(导入jar包) <dependencies&g ...