1

我的 Durandal 应用程序在 shell.js 中的启动逻辑需要根据某些条件逻辑将用户发送到两个可能的视图之一。基本上,如果以前没有选择某些选项,我会将它们发送到设置页面,否则我会将它们发送到正常的起始页面。

以前,在 Durandal 1.x 中,我只在调用激活时传递一个指示起始模块的字符串。但在 Durandal 2.x 中已被弃用。

所以首先,我想知道从路由数组的角度来看,推荐的方法是什么?我是否应该只注册两个路由,就好像启动模块都不是(如下所示)然后有条件地将另一个路由添加到默认路由''的数组?

{ route: "setup", moduleId: "setup", title: "Setup", nav: false },
{ route: "Students", moduleId: "students", title: "Students", nav: false }

我的问题的第二部分涉及如何处理调用 Web 服务的需要,这是我确定哪个模块是启动模块的条件逻辑的一部分。我的启动逻辑涉及检查浏览器的本地存储,但有时我还需要向服务器发出 ajax 请求以获取一些信息。

我的理解是 router.activate() 是一个承诺。我真的可以创建自己的承诺并在 ajax 调用完成后通过调用 router.activate() 来解决它吗?还是我需要另一种方法来处理它?我认为我可能会如何处理此问题的示例代码:

var deferred = $.Deferred();

//Setup and conditional logic here
var routes = setupRoutes();

$.get('/api/myStartupEndpoint')
 .done(function(results) {
    //check results and maybe alter routes
    deferred.resolve(router.map(routes).activate());
 });

return deferred.promise();

那有意义吗?我仍在将我的应用程序转换为 Durandal 2.0.1,所以我还不能尝试这个,但不管它是否可以,我都想知道在这种情况下推荐的方法是什么。

4

1 回答 1

2

我这样做的方式是这样的——实际上我认为这与你已经在想的方式相似,所以我希望它是有道理的:

  1. 在您的 main.js 中,无论在什么情况下,都将您的应用程序根目录设置为相同的模块。由于 D2 的主要功能之一是子路由器,我建议使用模块名称“root”作为应用程序根目录,因为它更容易与“shell”模块(我用于设置子路由器)区分开来:

    app.start().then(function () {
        app.setRoot("root", "entrance");
    });
    
  2. 在您的根模块中,按照您的描述设置路由:

    { route: "setup", moduleId: "setup", title: "Setup", nav: false },
    { route: "students", moduleId: "students", title: "Students", nav: false }
    
  3. 当您的根模块激活时,检查用户是否已设置。使用该检查的结果来确定您是否希望将用户发送到设置页面或学生页面。但是请注意,您必须在重定向之前激活您的路由器;您可以$.when在这里帮助您:

    var checkUserSetup = function () {
        var deferred = $.Deferred();
    
        // check local storage, fire off ajax request, etc.
        // resolve the deferred once you know if the user is setup or not
        deferred.resolve(false);
    
        return deferred.promise();
    };
    
    root.activate = function() {
        mapRoutes();
    
        var deferred = $.Deferred();
    
        $.when(checkUserSetup(), router.activate()).done(function(isUserSetup) {
            if (isUserSetup) {
                router.navigate("students");
    
            } else {
                router.navigate("setup");
            }
    
            deferred.resolve();
        });
    
        return deferred.promise();
    }
    

希望这也能回答您问题的第二部分;但以防万一 - 是的,您可以从该activate方法返回一个承诺,并且 durandal 将“阻止”,直到您解决了该承诺。但是,请注意路由器的activate方法也返回一个承诺- 所以你的代码不会完全工作。你正在用另一个 deferred 解决你的 deferred;你需要做更多这样的事情:

root.activate = function() {
    var deferred = $.Deferred();

    //Setup and conditional logic here
    var routes = setupRoutes();

    $.get('/api/myStartupEndpoint')
        .done(function(results) {
            //check results and maybe alter routes
            //don't resolve the deferred until the router has completed activation
            router.map(routes).activate().done(deferred.resolve);
        });

    return deferred.promise();
}

希望有帮助。

于 2013-11-12T22:06:20.053 回答