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

 附:请求对象和事件循环

原文地址:https://www.cnblogs.com/anlen/p/4631085.html