zoukankan      html  css  js  c++  java
  • 深入理解Node.js基于事件驱动的回调

    回调和异步调用的关系

    首先明确一点,回调并非是异步调用,回调是一种解决异步函数执行结果的处理方法。在异步调用,如果我们希望将执行的结果返回并且处理时,可以通过回调的方法解决。为了能够更好的区分回调和异步回调的区别,我们来看一个简单的例子,代码如下:

    function waitFive(name, function_name){
        var pus = 0;
        var currentDate = new Date();
        while(pus < 5000){
            var now = new Date();
            pus = now - currentDate;
        }
        function_name(name);
    }
    
    function echo(name){
        console.log(name);
    }
    
    waitFive("bob", echo);
    
    console.log('its over');

    以上代码是一个回调逻辑,但不是一个异步代码逻辑,因为其中并没有涉及 Node.js 的异步调用接口。waitFive()函数执行时,整个代码执行过程都会等待 waitFive() 函数的执行,而并非如异步调用那样waitFive未结束,还会继续执行console.log(‘its over’); 

    因此,回调还是一种阻塞式调用。

    异步函数往往不是直接返回执行结果,而是通过事件驱动方式,将执行结果返回到回调函数中,之后在回调函数中处理相应的逻辑代码。

    Node.js中很多API的调用模式是异步调用的,因此在学习Node.js过程中理解异步调用、同步调用和回调是非常重要的。

    为什么异步函数需要回调函数?

    先看这样一个例子:

    var dns = require('dns');  // require dns 模块
    var address = dns.resolved4('www.baidu.com', function(address){});//dns 同步解析
    
    console.log(address);

    当我们获取address值时,会出现异常,提示address没有定义undefined。打印出address,可以看到第二个例子结果为null,原因很简单,异步函数dns.resolve4()还未执行结束时,就已经执行到 console.log(address),因此最终 address 为 null。既然异步函数出现这个问题,我们就可以使用回调去获取函数。如下代码,通过回调函数获取执行的结果 address 值:

    var dns = require('dns');
    dns.resolve4('www.baidu.com', function(address){
        console.log(address);
    })

    Node.js —— 基于事件驱动的回调

    为什么它对我们用 Node.js 写网络应用是具有意义的?

    当我们使用 http.createServer 方法的时候,我们当然不只是想要一个侦听某个端口的服务器,我们还想要它在服务器收到一个HTTP请求的时候做点什么。问题是,这是异步的:请求任何时候都可能到达,但是我们的服务器却跑在一个单进程中。

    写PHP应用的时候,我们一点也不为此担心:任何时候当有请求进入的时候,网页服务器(通常是Apache)就为这一请求新建一个进程,并且开始从头到尾执行相应的PHP脚本。

    我们先来看一个基于Node.js简约而不简单的HTTP服务器:

    var http = require("http");
    
    http.createServer(function(request, response){
        response.writeHead(200, {"Content-Type": "text/plain"});
        response.write("Hello World");
        response.end();
    }).listen(8888);

    那么在我们的Node.js程序中,当一个新的请求到达8888端口的时候,我们怎么控制流程呢?

    嗯,这就是Node.js/JavaScript的事件驱动设计能够真正帮上忙的地方了 —— 虽然我们还得学一些新概念才能掌握它。让我们来看看这些概念是怎么应用在我们的服务器代码里的。

    我们创建了服务器,并且向创建它的方法传递了一个函数。无论何时我们的服务器收到一个请求,这个函数就会被调用。我们不知道这件事情什么时候会发生,但是我们现在有了一个处理请求的地方:它就是我们传递过去的那个函数。至于它是被预先定义的函数还是匿名函数,都无关紧要了。这个就是传说中的 回调(Node.js中的异步回调)。

    让我们再来琢磨琢磨 [ Node.js中的异步回调 ] 这个概念。

    我们怎么证明在创建完服务器之后,即时没有HTTP请求进来,我们的回调函数也没有被调用的情况下,我们的代码还继续有效呢?试试这个:

    var http = require("http");
    
    http.createServer(function(request, response){
        console.log("Request received.");
        response.writeHead(200, {"Content-Type": "text/plain"});
        response.write("Hello World");
        response.end();
    }).listen(8888);
    
    console.log("Server has started.");

    注意:在匿名回调函数触发的地方,我们用 console.log 输出了一段文本;在HTTP服务器开始工作之后,也输出一段文本。

    当我们与往常一样,运行 node server.js 时,它会马上在命令行上输出 “Server has started.”。当我们向服务器发出请求(在浏览器访问http://localhost:8888),“Request received.”这条消息就会在命令行中出现。(请注意,当我们在服务器访问网页时,我们的服务器可能会输出两次“Request received.”。那是因为大部分浏览器都会在你访问 http://localhost:8888 时尝试读取 http://localhost:8888/favicon.ico) —— 这就是事件驱动的异步服务器端 JavaScript 和它的回调啦! 

  • 相关阅读:
    【转】Android WiFi 经常掉线出现的几个原因分析!
    如何分析解决Android ANR
    如何分析和研究Log文件 ,如何看日志信息
    Force removing ActivityRecord no saved state问题的原因分析
    win7下彻底卸载和重装mysql
    mysql的基本操作命令
    mysql 启动,停止,重启
    解决mysql登录报错ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)问题
    一个轻量级的基于 .NET Core 的 ORM 框架 HSQL
    C# ref引用参数与out输出参数的使用与区别
  • 原文地址:https://www.cnblogs.com/samve/p/9589081.html
Copyright © 2011-2022 走看看