Javascript 如何生成需要其子函数信息的回调

Javascript 如何生成需要其子函数信息的回调,javascript,node.js,callback,haraka,Javascript,Node.js,Callback,Haraka,我在一个使用Node.js作为(smtp服务器)插件的项目中工作 这是Node.JS,我在回调方面有点小问题。我无法将此特定代码转换为使用回调 这是我的代码: exports.hook_data = function (next, connection) { connection.transaction.add_body_filter('', function (content_type, encoding, body_buffer) { var header = con

我在一个使用Node.js作为(smtp服务器)插件的项目中工作

这是Node.JS,我在回调方面有点小问题。我无法将此特定代码转换为使用回调

这是我的代码:

exports.hook_data = function (next, connection) {
    connection.transaction.add_body_filter('', function (content_type, encoding, body_buffer) {
        var header = connection.transaction.header.get("header");
        if (header == null || header == undefined || header == '') return body_buffer;

        var url = 'https://server.com/api?header=' + header ;
        var request = require('request');
        request.get({ uri: url },
          function (err, resp, body) {
              var resultFromServer = JSON.parse(body);
              return ChangeBuffer(content_type, encoding, body_buffer, resultFromServer);
          }
        );
    });
    return next();
}
此代码不起作用,因为它不等待请求的回调继续。我需要在下一步()之前完成请求。

这些是要求:

  • 在导出的末尾。hook_data必须返回
    next()
    。但它只需要在请求后返回
  • 我需要在
    add\u body\u filter
    中返回
    缓冲区
    ,但我需要使用从服务器获取的信息创建缓冲区
  • 要发出Get请求,我需要使用一个参数(
    标题
    ),该参数只有在
    add\u body\u filter
  • 因此,问题是我不能在
    add\u body\u filter
    之前发出请求,并将结果放入回调中,因为我需要发出请求的参数仅在
    add\u body\u filter


    有什么建议吗?

    除非您愿意使用同步、阻塞功能,否则不可能满足您编号的要求

    我会检查每个需求背后的原因,看看您是否以不同的方式实现了目标


    从表面上看,只要看看你那里的代码,我就会寻找一种方法来改变
    exports.hook_data
    的契约,这样你就可以从
    请求内部调用
    next()
    。get
    回调。

    使用Async.js或promission

    异步实现:

    exports.hook_data = function (next, connection) {
      async.waterfall([
        function( done ) {
          connection.transaction.add_body_filter('', function( content_type, encoding, body_buffer ) {
            var header = connection.transaction.header.get("header");
            if ( header == null || header == undefined || header == '' ) {
              done(null, body_buffer);
            }
            done(null, header);
          });
        },
        function( header, done ) {
          var url = 'https://server.com/api?header=' + header;
          var request = require('request');
          request.get({ uri: url },
            function( err, resp, body ) {
              // do something if there's an error
              var resultFromServer = JSON.parse(body);
              done(null, ChangeBuffer(content_type, encoding, body_buffer, resultFromServer));
            }
          );
        }
      ], function( error, buffer ) {
        // do something if there's error
        next(buffer);
      });
    }
    
    这里有很多内容,我建议你阅读上面的文档。本质上,它将每个异步调用分解为它所在的函数块,并等待它返回,然后再继续到下一个块


    同样,由于这些都是异步的,Node将这些任务提交给IO事件循环,并在那里处理(非阻塞)。当这个线程正在等待时,它可能会在这个请求等待时转到下一个请求。

    查看Haraka手册,我看不出头对
    添加\u body\u过滤器有任何依赖性。此外,您的代码不显示对
    添加\u body\u过滤器
    的任何依赖关系。所以你的第三个要求看起来是无效的

    考虑到这一点,我认为下面的伪代码(因为我无法测试它)应该适合您

    exports.hook_data = function (next, connection) {
        var header = connection.transaction.header.get("header");
        if (header == null || header == undefined || header == '') {
            return next();
    
        var url = 'https://server.com/api?header=' + header ;
        var request = require('request');
        request.get({ uri: url },
            function (err, resp, body) {
                var resultFromServer = JSON.parse(body);
                connection.transaction.add_body_filter('', function (content_type, encoding, body_buffer) {
                    return ChangeBuffer(content_type, encoding, body_buffer, resultFromServer);
                });
                next();
            }
        );
    }
    
    如果Haraka手册未能突出标题对
    add_body\u filter
    的依赖性和/或您根据实际经验发现了它,那么Quy的方法似乎是可行的


    如果您想知道如何处理我使用的
    Q
    代码的每个部分的优先级,您可以通过几个步骤来使用它:

  • npm安装q

    var request = require('request');
    var Q = require('q');
    
    exports.hook_data = function () {
       var url, header;
       Q()
       .then(function(){
         connection.transaction.add_body_filter('', function(content_type, encoding, body_buffer) {
    
          header = connection.transaction.header.get("header");
    
          if (header == null || header == undefined || header == ''){return body_buffer;}
          url = 'https://server.com/api?header=' + header ;
    
       })
       .then(function(){
    
           request.get({ uri: url }, function (err, resp, body) {
    
               var resultFromServer = JSON.parse(body);
    
               return ChangeBuffer(content_type,encoding,body_buffer,resultFromServer);
           });
    
       })
    
    }
    
  • async
    场景中,使用
    q
    进行回调比我认为的其他方法更好

    JavaScript本质上是异步的。异步是一种编程语言 提供非阻塞代码特性的模式,即不 停止或不依赖其他函数/进程来执行 特定代码行。 参考:

    来自维基百科

    Node.js提供了事件驱动的体系结构和非阻塞I/O API,旨在优化实时web应用程序的吞吐量和可伸缩性

    你能做什么

  • 使用睡眠/等待ie
    setTimeout
    (不推荐)
  • 使用一些异步库,如(推荐)
  • 使用一些像

  • 您不能在Javascript中使用异步函数,但要求它同步运行。这根本不可能。如果您有一个异步操作,那么必须编写代码以异步使用它。这意味着返回结果时使用承诺或回调,而不是通过函数的返回值,因为函数将在异步操作完成之前返回。您可能会从阅读本文中受益。您能否将回调传递给
    ChangeBuffer
    ?您在哪里使用
    body\u buffer
    (请参见第4行)以及
    ChangeBuffer的结果(content\u type,encoding,body\u buffer,resultFromServer)
    (请参见返回的第11行)?我猜哪里都没有,对吧?@AlexanderElgin
    add\u body\u filter
    的返回是一个缓冲区,这个缓冲区包含电子邮件的正文。我不直接使用它,服务器在处理电子邮件时使用它。我编写ChangeBuffer以便在需要时传递回调。您可以使用Async.js或Promissions来控制流吗?否则,老实说,你最终会得到一个非常糟糕的解决方案。遗憾的是,你不能在add\u body\u过滤器之外使用connection.transaction.header.get(“header”)。您可以在其他事件中使用它,但在数据事件中它将始终返回空值:(从上面的脚本中您确定它是Q的正确用法吗?对此表示怀疑!是的,我完全确定。但不是最佳方法。可能最好的方法是使用
    Q。所有
    以确定所需的数据和
    。展开
    继续执行步骤。