1

Mariotteを使用してモジュールの依存関係の解決を練習しようとしていますRequire.js。最近、ファイルを遅延してソースする方法を学ぼうとしました。.jsアプリケーションの起動時ではなく、必要なときにのみ関連ファイルをロードします。しかし、これは悪夢であることが証明されています。次のコード フラグメントは、私が現在やろうとしている方法です。

define(['app'], function(App) {
    App.module('Header', function(Header, App, Backbone, Marionette, $, _) {

        this.doSomething = function() { alert('Did something!'); }
        this.getSomething = function() { return 'Something'; }

    }
});

作業を行う前にロードするdoSomething必要があるとします。subdep次のように確認できます:が呼び出さsubdepれたときにのみ読み込まれるChromeDevtools で確認できthis.doSomething()ます。

this.doSomething = function() {
    require(['subdep'], _.bind(function() {
        alert(this.SubDep.showSomething());
    }, this));
}

ここから先、対処することを楽しみにしている問題/質問がいくつかあります。

  1. _.bind()の値を保持するために使用する必要がありますthis。またrequire(...)、コードを視覚的に汚染します。おそらくカスタマイズすることで、それを回避する方法はありMarionette.Module.prototypeますか?次のようなものが理想的です。

    this.doSomething = function() { alert(this.SubDep.showSomething()); }
    myRequireHash: {
        'this.doSomething' : ['subdep'],
        'this.getSomething' : ['subdep', 'underscore']
    }
    
  2. this.getSomething呼び出し元に値を返す必要があるとします。requireステートメントが非同期ロードを開始し、すぐに戻るため、次のステートメントは明らかに機能しません。これを回避するにはどうすればよいですか? 実際に必要なときに依存関係をロードし、値を返すこともできる必要があります。

    this.getSomething = function() {
        require(['subapp'], _.bind(function() {
            return this.SubApp.getSomething();
        }, this));
    }
    
  3. ポイント 2 の拡張として、発信者が を呼び出した後に呼び出す必要があるとしthis.doSomething() ますthis.getSomething()。呼び出しは非同期であるため、2 つの関数が順番に呼び出されるようにするために使用できるfromをrequire返すことはできますか? もしそうなら、どうやって?promisethis.getSomething()

アシム


アップデート

ポールのアイデアを使用して、私が自分の状況にどのように取り組んだかを次に示します。

function RequirePromise (pListDeps, oContext, fnFunc)
{
    return $.Deferred(function(oDef)
    {
        require(pListDeps, function()
        {
            var pArgs = [];
            if (fnFunc)
            {
                if (oContext) fnFunc = _.bind(fnFunc, oContext);
                pArgs.push(fnFunc.apply(fnFunc, arguments));
            }
            oDef.resolveWith(oContext, _.union(pArgs, arguments));
        });
    }).promise();
}

pListDepsロードする依存関係のリストです。oContextpromise 関数が存在する優先されるデフォルトのコンテキストです。fnFuncは、指定された関数で実行されるオプションの関数です (関数へのチェーンなしでthen)。関数からの戻り値は、then/の最初のパラメーターとして使用できますdone。読み込まれた依存関係は、2 番目以降のパラメーターとして使用できます。これを次のいずれかとして使用できます。

RequirePromise(['app'], this).done(function(App) { console.log(arguments); }

RequirePromise(['app'], this, function(App) { console.log(App); return true; })
    .done(function(oRet, App) { console.log(arguments); }

RequirePromise(['app'], this)
    .then(function() { return RequirePromise(['subapp']); })
    .done(function() { console.log('Both app and subapp loaded!'); }

ありがとうポール =)

4

1 に答える 1

3

すべての非同期メソッドに対してコールバックまたは deferreds/promise を提供しないと、本当にやりたいことができません。

waitJavaScript には//他の言語のようにwaitUntilwaitFor非同期タスクが完了するのを待つという概念はありません。実際、ブラウザが「ハング」するため、ほとんどの場合、これを実行したくありません。

この jsfiddleは、私が言いたいことの一例です。

以下の JS は、jQuery Deferredsに関するある程度の知識があることを前提としています。

HTML:

<script>
require = {
    paths: {
        "jquery": "http://code.jquery.com/jquery-2.0.3",
        "mymodule": "https://rawgithub.com/gitgrimbo/5689953/raw/9b44d7e5f504b2245331be3ed3fcbb7bf8635da6/gistfile1"
    }
};
</script>
<script src="//cdnjs.cloudflare.com/ajax/libs/require.js/2.1.8/require.min.js"></script>
<button>click me</button>

JS (1):

dfdRequirerequire()jQuery promise オブジェクトを呼び出して返す関数です。

のコールバックrequire()は内部的なものであり、によって返される依存関係はrequire()、遅延を解決するために使用されます。

基本的に、これはコールバックベースのシステムからプロミスベースのシステムに変換されます。

function dfdRequire(deps) {
    return $.Deferred(function(dfd) {
        require(deps, function() {
            dfd.resolve.apply(dfd, arguments);
        });
    }).promise();
}

これは実際には次のように削減できます。

function dfdRequire(deps) {
    return $.Deferred(function(dfd) {
        require(deps, dfd.resolve.bind(dfd));
    }).promise();
}

JS (2):

上記の関数を使用するダミーのアプリ モジュールを作成します。

getSomething()メソッドを使用してモジュールdfdRequire()をロードし、メソッドを使用して実際にモジュールを使用します。"mymodule"then()

に渡された関数then()は、mymodule値を大文字にして使用し、この新しい値を返します。これは、メソッドが戻るときに、実際には大文字の値を返すことを意味します。

define("app", ["jquery"], function($) {
    return {
        doSomething: function(value) {
            console.log("doSomething with " + value);
        },
        getSomething: function() {
            // Load the dependency as a promise, and return that promise to the caller,
            // so the caller can also await its resolution.
            return dfdRequire(["mymodule"]).then(function(mymodule) {
                console.log("Loaded mymodule. Value=" + mymodule);
                // return the module value as-is,
                // or optionally perform some transformation.
                return mymodule.toUpperCase();
            });
        }
    };
});

JS (3):

アプリをプルして、そのメソッドを使用します。

app.getSomething()約束を返します。この promise をチェーンで使用します (promise 呼び出しをチェーンできることを示すため)。まず、値を出力する値が渡されconsole.log()ます。次に、 を呼び出しますapp.doSomething()

require(["jquery", "app"], function($, app) {
    console.log($.fn.jquery);
    $("button").first().click(function(evt) {
        console.log(evt);
        app.getSomething()
            .done(console.log.bind(console))
            .done(app.doSomething.bind(app));
    });
});

Function.bind()と書くこともできるものの省略形として使用します。

        app.getSomething()
            .done(function(value) {
                console.log(value);
            })
            .done(function(value) {
                app.doSomething(value);
            });

結果:

2.0.3
Object { originalEvent=Event click, type="click", timeStamp=88448339, more...}
Loaded mymodule. Value=my-library
MY-LIBRARY
doSomething with MY-LIBRARY
于 2013-09-06T13:41:02.063 に答える