4

我正在尝试使用 Node.js 为我处理一些可编写脚本的 URL 重定向。它工作得很好,但脚本需要采用尽可能简单的格式,因为它将由其他人管理。

我想做的是使用构建器模式,这样我就可以拥有以下内容:

redirectWhen.isMobileDevice().urlMatches("http://www.somewhere.com").thenGoTo("http://mobile.somewhere.com");
redirectWhen.urlMatches("http://subdomain.somewhere.com").thenGoTo("http://www.somewhere.com/somefolder/");

然后我会根据结果重定向(基本上匹配链中所有项目的最后一个获胜)。如果你想象所有的功能(isMobileDevice()&urlMatches(...)做一些简单的字符串检查等等,那么一切都很好。

但我需要这个isMobileDevice()函数来执行一个 HTTP 请求。这意味着有一个回调函数在响应完成时被调用。是否有可能做到这一点并且仍然保持构建器模式完好无损?我想我可以做类似的事情:

redirectWhen.isMobileDevice(function() {
  urlMatches("...").thenGoTo("...");
});

但这比我想要的增加了脚本的复杂性。管理这些脚本的人知道基本的 JavaScript,但如果他们必须开始嵌套回调,我想他们很快就会感到困惑。

我猜我正在尝试实现一些在这里不可能的事情,但我自己对 JS 的了解还不够,无法证实这一点!

4

3 回答 3

1

这是完全可能的;您的构建器在每一步都返回一个中间对象,在最后一步中,您最终将各个部分放在一起并调用最终函数。

function redirectWhen() {
    var building = {};  // saved state goes here

    // actually implement redirection
    function build() {
        // expects building = { source: "...", target: "...", mobile: optionalBoolean}            
        if (building.mobile) {
           checkMobile();
        } else {
           finishBuild();
        }
    }

    function checkMobile() {
        // check if actually mobile by making an HTTP request
        // in the success callback, calls finishBuild - fails otherwise
        // ..
    }

    function finishBuild() {
        // accessible only if mobile not requested, or if requested and mobile check passed
        // ..
    }

    // prepare the second step
    var urlMatches = function(url) {
        building.source = url;
        return { thenGoTo: function(target) { building.target = target; build(); } }
    }

    // return the next steps
    return { 
       isMobileDevice: function() { builder.mobile = true; return urlMatches; },
       urlMatches: urlMatches
    }
}

为了支持您的移动测试,您可以将构建分为两部分(检查和回调);但这对用户来说是不透明的,他们甚至不知道任何地方都有构建功能。

于 2013-01-23T10:57:34.643 回答
1

您不必为了使其异步工作而放弃优雅的构建模式。您可以创建一个节点链表,每个节点在成功时调用下一个节点。

我使用一个和多个实现设置了一个小提琴。一些注意事项:ChainChainNode

  • 每个ChainNode都有一个execute()方法和一个在完成自己的处理时nextNode需要调用的方法。next()例如,URL 模式匹配器仅在 URL 匹配模式时才调用下一个节点,否则它只会返回(中断执行链)。
  • IsMobileNode可以通过从next()回调调用到一些异步调用(例如 AJAX)来实现。在小提琴中,一个简单setTimeout的演示了这个概念。
  • Chain保留一个head指示开始执行的位置和附加tail新节点的位置。该chain(nextNode)方法确保链条完好无损。
  • 和方法只是创建一个节点urlMatches(urlPattern)并将isMobileDevice()其附加到链中。
  • thenGoTo()方法链接最终节点以启动重定向。然后,它执行从head.
于 2013-01-23T12:09:06.250 回答
0

Dan Lee 对我的问题的评论也帮助我找到了 Q 库:https ://github.com/kriskowal/q 。这肯定会对我想要的有所帮助,尽管它不像其他答案那么简单。

于 2013-01-23T14:56:12.507 回答