2016-10-09 10 views
0

node.jsアプリケーションのリファクタリングに問題があります。 accessResourceは、変更する権限のないコールバックを使用する任意の関数の単なるモックではありません。次の(非常に仮説的な)例を考えてみましょう。スコープを失うことなくnode.js関数をリファクタリングする

var express = require('express'); 
var app = express(); 

app.get('/', function(request, response) { 
    accessResource(request, response, function sendResponse(err, data) { 
    if (err) { 
     return response.status(500).send({"message": err}); 
    } else { 
     return response.status(200).send({"message": data}); 
    } 
    }); 
}); 

app.listen(8080); 

私は最終的には、独自のモジュールに移動できるように、スタンドアロン関数にsendResponseをリファクタリングしたいと思います。 応答sendResponseの範囲で使用できないため、

app.get('/', function(request, res) { 
    accessResource(request, response, sendResponse); 
}); 

function sendResponse(err, data) { 
    if (err) { 
     return response.status(500).send({"message": err}); 
    } else { 
     return response.status(200).send({"message": data}); 
    } 
} 

今、明らかにこれは、もはや機能しません。

+0

あなた自身の質問にお答えしました。別の関数でsendResponseをラップしたいとします。 –

答えて

3

あなたの人生を変えるパズルの部分は、高次関数です。

私はあなたの人生のすべての問題を解決しようとしているとは言いませんが、どのように動作するかに慣れれば、このような問題はずっと簡単になります。

ミドルウェアとその他のものの設定について学ぶことができますが、これは具体的に表現の領域にある唯一の解決策です。機能的な構成は、JSを通じて喜んで使用されるものです。 ES6で

function makeResponseHandler (response) { 
    function sendResponse (err, data) { 
     return err 
     ? response.status(500).send({"message": err}) 
     : response.status(200).send({"message": data}); 
    } 
    return sendResponse; 
} 

、私はちょうどとしてこれを書くかもしれない:話の教訓は、関数が値として渡すことができるということである

function makeResponseHandler = (response) => (err, data) => err 
    ? response.status(500).send({"message": err}) 
    : response.status(200).send({"message": data}); 


app.get("./", (request, response) => { 
    accessResource(request, response, makeResponseHandler(response)); 
}); 

。あなたはそれを知っているかどうかに関わらず、すでにこれを知っています。あなたはコールバックを使用しています、あなたは値として渡しています。

JSの超強力な機能は、関数を値として返すことができるということです。
内に作成する関数の中には、関数内にあるその他のものにアクセスできます。あなたが外に価値として返すときでさえ。

したがって、使用するresponseを参照するファクトリの中にコールバック関数を作成すると、工場で作成したコールバックで常にその応答を利用できます。

function rememberX (x) { 
    return function retrieveX() { return x; }; 
} 

const get32 = rememberX(32); 
const get24 = rememberX(24); 
const getTheAnswer = rememberX(42); 

const x = 88; 
get32(); // 32 
get24(); // 24 
getTheAnswer(); // 42 

それらはすべて関数の各インスタンスが行われたときに外側の関数が与えられたことをxの値を覚えていることに留意されたいです。また、外部の値がxであることを気にする人はいないことに注意してください。それらはすべて、参照している内部のxです。

このようにしたい場合は、responseという外部関数を使用して、通常のコールバックのように動作する関数を返すことができます。

これは、近代的なJS開発の他の多くの場合に便利です。

const pluck = key => obj => obj[key]; 
const greaterThanX = x => y => y > x; 
const getName = pluck("name"); 

const people = [{ name: "Bob" }, { name: "Susan" }, 
       { name: "Doug" }, { name: "Sarah" }]; 

people.map(getName) // ["Bob", "Susan", "Doug", "Sarah"] 
    .map(pluck("length")) // [3, 5, 4, 5] 
    .filter(greaterThanX(3)); // [5, 4, 5] 

少し不自然、それはあなたがページネーションのデータが利用可能なユーザのフィルタ基準を用意して、または可能性がある場合には、高度なフィルタを設定するには直ちに適用だが、あなたはそう、まだ実際に使用可能なデータを持っていません関連するデータのリストを渡し、アセンブリラインを監視する機能を構築したいだけです。

+0

これは本当にそれを明確にします!あなたがすでに推測しているように、私は高次関数の存在を認識していますが、明らかに私はそれをすべてまとめることができませんでした。 JavaEEの日とJSの夜は、その通行料を取る... – Oli

0

あなたはどこでもあなたのコールバックを定義するが、として渡す場合があります...私は別の関数でsendResponseをラップしなければならないように思えるが、私はここでの基本的な考え方をしないのですように、すべてのほとんどは私が感じますあなたが呼び出し関数にバインドする必要がある機能とアクセスへのコールバックの引数は、それがthis.arguments[0]this.arguments[1]

function doStg(a,b,cb){ 
 
    var e = false; 
 
     d = 10; 
 
    return cb(e,d); 
 
} 
 

 
function callback(err,dat){ 
 
return !err ? this.arguments[0] + this.arguments[1] + dat : err; 
 
} 
 

 
console.log(doStg(1,2,callback.bind(doStg)));

のような引数です

これは醜いですが実行可能です。

コールバックをresponseオブジェクトにバインドし、コールバック内のthisとしてアクセスすることもできますが、その場合は、すなわちaccessResource(request, response, sendResponse.bind(response));になり、コールバック内のオブジェクトにはthisとアクセスします。

関連する問題