1

我有一个需要执行一些引导/启动的应用程序,例如:

  • 阿贾克斯
  • 动态需求
  • 路由,设置其他东西

在能够运行之前。

我现在很难将这些任务组织在一起。尤其是异步行为让我头疼。目前我正在使用事件来共享获取的结果并观察应用程序的状态。不幸的是,这导致了酿酒学上的不便。然后我尝试使用一些承诺库,如 q、jquery.defered,但它们并不真正符合我的问题。

这是代码的简化版本:

// this could be an ajax call fetching some user data
var fetchUser = function() {
    var user = {};
    // lets emulate the ajax call with setTimeout
    setTimeout(function() {
        // set some values
        user.username = 'bodo';
        user.password = 'helloKitty';
        // return the user object we "fetched"
        return user;
    }, 300);
};

// this could fetch some config or some requirejs modules
var fetchConfig = function() {
    var config = {};
    // we emulate this too...
    setTimeout(function() {
        return config;
    }, 200);
};

// this could be anything else like setting up some objects
var justSetUpSomething = function() {
    var someObj = {};
    someObj.router = 'this could be a router object for example';
    someObj.logger = 'or a logger';
    return someObj;
};

// in the final step everything should be merged together
// and be passed as event argument
var finalStep = function(user, config, someObj) {
    var mainObj = {};
    mainObj.user = user;
    mainObj.config = config;
    mainObj.someObj = someObj;
    // trigger some event system
    trigger('everything:ready', mainObj);
};​

也可以在以下位置查看:http: //jsfiddle.net/uzJrs/3/

我希望这能描述我的问题:

有三个完全不同的异步任务。当他们都准备好时,他们的结果必须合并并以某种方式传递给另一个对象。

事件使这可行,但远不能理解,承诺也不能真正让我开心。难道没有另一种有用的设计模式吗?

4

2 回答 2

2

首先,因为你已经有了 requirejs,你可以用它来加载你的三个模块。Requirejs 异步并行解析依赖关系,并在加载时调用最终的工厂函数。

但是,每个 Deferred 库也提供了合并 Promise 的函数:当所有单个的 Promise 都被解决时,合并的 Promise 被解决,或者如果其中一个被拒绝,则被拒绝。各自的功能是Q.alljQuery.when

function fetchX() {
    var d = new $.Deferred();
    asynchronousThing(function callback(x) {
        d.resolve(x);
    });
    return d.promise();
}
$.when(fetchX(), fetchY(), …).then(function finalStep(x, y, …) {
    // merge everything together
    return new Event();
}).done(function readyCallback(e) {
    // this is effectively your 'everything:ready' "event"
});
于 2012-09-17T16:55:45.537 回答
1

听起来您的大部分功能实际上是同步的,只要解决了依赖项(即不做任何异步操作,它们可能只是异步加载。如果您使用的是 require.js,您是否尝试过简单地使用它的功能来config制作从代码的角度来看someObjrequire调用是同步的,使用define? 那么你只需要担心必须是异步的调用(fetchUser)。

// In app/main.js perhaps?
define(["data/user",
            "app/config",
            "app/someObject",
            "app/events"], 
    function(user, config, someObj, eventBus) {
        // By the sound of it config and someObj are ready once loaded
        var mainObj = {"config": config, "someObj": someObj};
        eventBus.register_once("data:user:loaded", function(user) {
            mainObj.user = user; 
            eventBus.trigger("everything:ready", mainObj);
        });
        user.fetchUser()
});

// in data/user.js
define(["app/config", "app/events", "vendor/jquery"],
    function(config, eventBus, $) {
        function user_loaded(user) {
            eventBus.trigger("data:user:loaded", user);
        }
        function fetchUser() {
            $.get(config.dataendpoint + "/user/1", user_loaded);
        }
    return {"fetchUser": fetchUser};
});
于 2012-09-17T16:47:34.180 回答