2

JavaScript で非同期リクエストを行いたいが、何らかの状態をコールバック メソッドに渡したいとします。以下は、JavaScript でのクロージャーの適切な使用法ですか?

function getSomethingAsync(someState, callback) {
    var req = abc.createRequestObject(someParams);
    req.invoke(makeCallback(someState, callback));
}

function makeCallback(someState, callback) {
    return function getSomethingCallback(data) {
        var result = processDataUsingState(data, someState);
        callback(result); // alternately/optionally pass someState along to result
    }
}

そうでない場合、より良い、またはより慣用的な方法はありますか?

4

4 に答える 4

2

これに関して差し迫った問題は見当たりません。クロージャーは多くの理由で強力です。その理由の 1 つは、状態を維持するためにグローバル変数を使用する必要がなくなることです。

とはいえ、クロージャに関して注意する必要があるのは、IE で通常発生するメモリ リークだけですが、通常は DOM 要素とそれに関連付けられたイベント ハンドラに関連する IIRC です。

続行!

于 2008-10-30T19:08:58.490 に答える
1

より慣用的な方法は を使用するFunction.bindことであり、クロージャーを作成するためにコードを複製する必要はありません。簡単な例 (カスタム コードがないもの) を使用して説明します

/**
 * Retrieves the content of a url asyunchronously
 * The callback will be called with one parameter: the html retrieved
 */
function getUrl(url, callback) {
    $.ajax({url: url, success: function(data) {
        callback(data);
    }})    
}

// Now lets' call getUrl twice, specifying the same 
// callback but a different id will be passed to each
function updateHtml(id, html) {
    $('#' + id).html(html);
}


// By calling bind on the callback, updateHTML will be called with 
// the parameters you passed to it, plus the parameters that are used
// when the callback is actually called (inside )
// The first parameter is the context (this) to use, since we don't care,
// I'm passing in window since it's the default context
getUrl('/get/something.html', updateHTML.bind(window, 'node1'));
// results in updateHTML('node1', 'response HTML here') being called
getUrl('/get/something-else.html', updateHTML.bind(window, 'node2'));
// results in updateHTML('node2', 'response HTML here') being called

Function.bindは新しいので、下位サポートが必要な場合は、の互換性セクションを参照してください。 Function.bind

最後に、質問が jQuery としてタグ付けされていないことを知っています。これは、クロス ブラウザーの問題に対処せずに非同期関数を表示する最も簡単な方法でした。

于 2012-01-19T17:31:58.197 に答える
0

匿名関数を使用する方が良い(より良い):

function getSomethingAsync (someState, callback) {
    req.invoke (function (data) {
       var result = processDataUsingState (data, someState);
       callback (result);
    });
}
于 2008-10-30T19:05:51.367 に答える
0

call() / apply() を使用して、関数内の「this」の値を操作することもできます。

たとえば、非同期メソッドへの追加の引数が、コールバックで「this」として使用するオブジェクトであることを指定します。これは、jQuery がイベント コールバックで dom ノードを「this」に設定する方法です。

function getSomethingAsync(callback, scope) {
    var req = abc.createRequestObject(someParams);
    req.invoke(function(rsp) {
      callback.apply(scope, [rsp]);
    });
}

// usage:
getSomethingAsync(function() {console.log(this.someState)}, {someState:'value'});
于 2012-01-22T21:57:52.760 に答える