node.js中的回调

同步和阻塞:这两个术语可以互换使用,指的是代码的执行会在函数返回之前停止。如果某个操作阻塞,那么脚本就无法继续,这意味着必须等待。

异步和非阻塞:这两个术语可以互换使用,指的是基于回调的、允许脚本并行执行操作的方法。脚本无需等待某个操作的结果才能继续前进,因为操作结果会在事件发生时由回调来处理。使用异步方法,操作无需一个接一个地发生(自己注:就是并行了)。

@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层,嵌套过多可能会碰到深度嵌套的回调和控制流的问题。

附:请求对象和事件循环

时间: 2024-08-06 03:53:54

node.js中的回调的相关文章

Node.js权威指南 (10) - Node.js中的错误处理与断言处理

10.1 使用domain模块处理错误 / 272 10.1.1 domain模块概述 / 272 10.1.2 创建并使用Domain对象 / 274 10.1.3 隐式绑定与显式绑定 / 276 10.1.4 绑定回调函数与拦截回调函数 / 279 10.1.5 domain堆栈的弹出与推入 / 280 10.1.6 Domain对象的销毁 / 28610.2 Node.js中的断言处理 / 286 10.2.1 equal方法与notEqual方法 / 287 10.2.2 strictE

Node.js链式回调

由于异步的关系,代码的书写顺序可能和执行顺序并不一样,可能想先执行A再执行B,但由于异步可能B要先于A执行.例如在OC中使用AFnetworking请求数据然后刷新页面,由于网络请求是用block实现的异步方法,所以刷新的时候并没有数据,为了解决这个问题,一般会在请求响应结束在block中刷新页面(这就回出现循环引用的问题,不过node中不会出现). 上面是OC中异步执行中的链式回调,在node.js中也是使用这样的方法在回调中调用方法来实现链式回调. function logCar(car,c

笔记-Node.js中的核心API之HTTP

最近正在学习Node,在图书馆借了基本关于Node的书,同时在网上查阅资料,颇有收获,但是整体感觉对Node的理解还是停留在一个很模棱两可的状态.比如Node中的模块,平时练习就接触到那么几个,其他的一些模块暂时只会在学习的时候接触到,不常用便就荒废了.正所谓好记心不如烂笔头,多做笔记还是更有利于理解和记忆.自己做的总结也方便回头复习,所以决定踏上漫长的修炼之旅-- Node提供了许多API,其中一些比较重要.这些核心的API是所有Node应用的支柱,你会不停的用到他们. HTTP服务器 Nod

node.js如何使用回调

Node.js到处使用回调,尤其在有I/O(输入/输出)操作的地方. 下面是在一个Node.js中使用filesystem模块中从磁盘上读入文件内容示例一: var fs = require('fs'); fs.redFile('somefile.txt', 'urf8', function (err, data) { if (err throw err); console.log(data); }); 以下是所发生的事情: 1.fs(filesystem)模块被请求,以便在脚本中使用 2.将文

node.js中模块,require

在php,C++中都有命名空间的概念,命名空间主要是用来解决引入文件存在函数,类,变量重名的问题,在node.js中,没有命名空间这么复杂的概念,在node中,有模块的概念,也就是将功能性的代码都放在一起.然后引入,在本文件中使用.这种不会出现函数名,变量重名问题,在引入的模块中,都是以导入的方式注册的.看下面的例子: //circle.js var pi = 3.14; //计算圆的周长 exports.circle = function(r) { return 2 * pi * r; } /

node.js中net网络模块TCP服务端与客户端的使用

node.js中net模块为我们提供了TCP服务器和客户端通信的各种接口. 一.创建服务器并监听端口 const net = require('net'); //创建一个tcp服务 //参数一表示创建服务的一些配置 //参数二表示 事件 'connection' 监听回调函数 let server = net.createServer({ //表示是否允许一个半开的TCP连接,默认为false allowHalfOpen: false, //一旦来了连接,是否暂停套接字,默认为false pau

node.js中通过dgram数据报模块创建UDP服务器和客户端

node.js中 dgram 模块提供了udp数据包的socket实现,可以方便的创建udp服务器和客户端. 一.创建UDP服务器和客户端 服务端: const dgram = require('dgram'); //创建upd套接字 //参数一表示套接字类型,'udp4' 或 'udp6' //参数二表示事件监听函数,'message' 事件监听器 let server = dgram.createSocket('udp4'); //绑定端口和主机地址 server.bind(8888, '1

在Node.js中使用RabbitMQ系列二 任务队列

在上一篇文章在Node.js中使用RabbitMQ系列一 Hello world我有使用一个任务队列,不过当时的场景是将消息发送给一个消费者,本篇文章我将讨论有多个消费者的场景. 其实,任务队列最核心解决的问题是避免立即处理那些耗时的任务,也就是避免请求-响应的这种同步模式.取而代之的是我们通过调度算法,让这些耗时的任务之后再执行,也就是采用异步的模式.我们需要将一条消息封装成一个任务,并且将它添加到任务队列里面.后台会运行多个工作进程(worker process),通过调度算法,将队列里的任

node.js中的交互式运行环境-REPL

<Node.js权威指南>第2章Node.js中的交互式运行环境--REPL 开发者可以在该环境中很方便地输入各种JavaScript表达式并观察表达式的运行结果. 在学习Node.js框架的过程中,通过该运行环境的使用,我们可以很方便地了解Node.js中定义的各种对象所拥有的各种属性及方法.本节为大家介绍在REPL运行环境中操作变量 2.2 在REPL运行环境中操作变量 在REPL运行环境中,可以使用var关键字来定义一个变量并为其赋值,但是在输入了对其赋值进行的表达式后,该表达式的执行结