1

次のような起動/起動を実行する必要があるアプリケーションを入手しました。

  • ajax
  • 動的requirejs
  • ルーティング、何か他のものを設定する

実行する前に。

私は今、これらのタスクをしっかりと一緒に整理するのに苦労しました。特に非同期動作は私に頭痛の種を与えています。現在、取得した結果を共有し、アプリケーションの状態を監視するためにイベントを使用しています。残念ながら、これはワイン醸造的で不便ながらくたをもたらしました。次に、q、jquery.deferedなどのpromiseライブラリを使用してみましたが、実際には問題と一致しません。

これは、コードの簡略化されたバージョンです。

// 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/でも表示可能

これが私の問題を説明していることを願っています:

3つのまったく異なる非同期タスクがあります。すべての準備ができたら、結果をマージして、何らかの方法で別のオブジェクトに渡す必要があります。

イベントはこれを実行可能にしますが、理解できるとはほど遠いものであり、約束も私を本当に幸せにしません。他に役立つデザインパターンはありませんか?

4

2 に答える 2

2

最初は、requirejsがすでにあるので、それを使用して3つのモジュールをロードできます。Requirejsは依存関係を非同期かつ並列に解決し、それらがロードされるときに最終的なファクトリ関数を呼び出します。

ただし、すべてのDeferredライブラリには、Promiseをマージする関数もあります。マージされたライブラリは、すべての単一のライブラリが解決されると解決され、そのうちの1つが拒​​否されると拒否されます。それぞれの関数はとQ.allですjQuery.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を使用している場合は、その機能を使用して作成してみましたか ?を使用してコードの観点から同期的な呼び出しを行うと、非同期である必要がある呼び出しについてのみ心配する必要があります()。configsomeObjrequiredefinefetchUser

// 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 に答える