2016-05-15 5 views
4

Я использую рамки Экспресса и я следующий в одном из моих маршрутов файлов:NodeJS обратного вызова - Доступ к «Рез»

var allUsersFromDynamoDb = function (req, res) { 
var dynamodbDoc = new AWS.DynamoDB.DocumentClient(); 
var params = { 
    TableName: "users", 
    ProjectionExpression: "username,loc,age" 
}; 

dynamodbDoc.scan(params, function (err, data) { 
    if (err) { 
     console.error("Unable to query. Error:", JSON.stringify(err)); 
     res.statusCode = 500; 
     res.send("Internal Server Error"); 
    } else { 
     console.log("DynamoDB Query succeeded."); 
     res.end(JSON.stringify(data.Items)); 
    } 
}); 
} 

Я использую вышеуказанную функцию в одном из моих маршрутов:

router.get('/users', allUsersFromDynamoDb); 

Теперь обратный вызов, который я определяю при выполнении вызова «scan» на dynamodbDoc, может быть очень полезным, если он определен как отдельная функция. Я могу повторно использовать это для некоторых других моих маршрутов.

Но как я могу получить доступ к «res» внутри этой новой функции?

Я думаю, что я должен использовать «закрытие», но я не могу понять, как это правильно. Я думаю, что мне нужно, чтобы сохранить подпись новой функции обратного вызова ожидать 2 Params, «ERR» и «данные» в соответствии со следующей страницы:

http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html#scan-property

Любые идеи о том, как это можно сделать?

+0

Я думаю, что вы можете поместить обратный вызов в свою собственную именованную функцию, пока она находится в той же области действия, из которой вызывается 'dynamodbDoc.scan'. Здесь, из-за функции 'закрытия' JS, ваш обратный вызов будет иметь доступ к одному и тому же объекту' res' как 'dynamodbDoc.scan'. –

+0

О да, это вариант. Я должен был упомянуть об этом в своем описании вопроса. Но если я это сделаю, то функция обратного вызова будет недоступна вне функции allUserFromDynamoDB.Предположим, у меня была другая функция (для другого маршрута) 'getSpecificUserFromDynamoDB', откуда я тоже хотел ее использовать. Надеюсь, ясно, что я говорю. – vksinghh

+0

Проблема заключается в том, что если функция обратного вызова определена вне области действия 'allUsersFromDynamoDb', то она не будет иметь доступа к объектам' res' или req'. Вы можете найти обходное решение, которое я думаю (в зависимости от конкретного использования). –

ответ

2

Вы можете использовать эту функцию в качестве промежуточного слоя из каждых маршрутов, которые вы хотите http://expressjs.com/en/guide/using-middleware.html

Новый маршрут с промежуточного слоя:

var middlewares = require('./middlewares'), 
    controllers = require('./controllers'); 

router.get('/users', middlewares.allUsersFromDynamoDb, controllers.theRouteController); 

Промежуточное (middlewares.js), где проходят ваши данные req так что вы можете использовать эти данные везде у вас есть req:

exports.allUsersFromDynamoDb = function (req, res, next) { 
    var dynamodbDoc = new AWS.DynamoDB.DocumentClient(); 
    var params = { 
     TableName: "users", 
     ProjectionExpression: "username,loc,age" 
    }; 

    dynamodbDoc.scan(params, function (err, data) { 
     if (err) { 
      console.error("Unable to query. Error:", JSON.stringify(err)); 
      next("Internal Server Error"); 
     } else { 
      console.log("DynamoDB Query succeeded."); 
      req.dataScan = JSON.stringify(data.Items); 
      next(); 
     } 
    }); 
}; 

И, наконец, контроллер (controllers.js):

exports.theRouteController = function (req, res) { 
    // Here is the dataScan you defined in the middleware 
    res.jsonp(req.dataScan); 
}; 
+0

Спасибо за ответ Мишель! То, что я действительно надеялся сделать, это повторно использовать большую часть кода для «функции (err, data)», поэтому мне не нужно повторять его для других маршрутов, которые у меня есть. Я сделал что-то, основанное на вашем предположении использования промежуточного программного обеспечения, которое делало вещи немного более чистыми. Я буду публиковать то, что я сделал здесь, в качестве другого ответа, поскольку пространство в комментарии ограничено. – vksinghh

1

На основании ответа Michelem здесь я пытался что-то, что делает вещи немного чище и коды более многократное использование:

var allUsersFromDynamoDb = function (req, res, next) { 
var dynamodbDoc = new AWS.DynamoDB.DocumentClient(); 
var params = { 
    TableName: "users", 
    ProjectionExpression: "username,loc,age" 
}; 

dynamodbDoc.scan(params, function (err, data) { 
    req.err = err; 
    req.data = data; 
    next(); 
}); 
} 

Объявляет другую функцию:

var processUserResults = function (req, res, next) { 
if (req.err) { 
    console.error("Unable to query. Error:", JSON.stringify(req.err)); 
    res.statusCode = 500; 
    res.send("Internal Server Error"); 
} else { 
    console.log("DynamoDB Query succeeded."); 
    res.end(JSON.stringify(req.data.Items)); 
} 
}; 

И наконец, это:

router.get('/users', [allUsersFromDynamoDb, processUserResults]); 

Все, что нужно сделать в оригинале «функция (эээ, данные)» обратный вызов всегда устанавливаются 2 значения:

req.err = err 
req.data = data 

И позвони следующим(). И processUserResults можно аналогичным образом использовать для других маршрутов.

По-прежнему интересно узнать, есть ли другие эффективные решения.

Смежные вопросы