基本范围问题(javascript 和节点)
Basic scope issue (javascript and node)
嗨,我有一个非常简单(我认为)的 js 问题,我似乎被卡住了。
我正在尝试创建下面的路线。
从 bEtsy 函数中得到 console.logged 的是我希望在页面上显示的内容。但是 'body' 在该范围之外不可用。
app.get('/api/etsy/getListings',function(req, res){
bEtsy.getAllListings(req, res, function(err, body) {
// console.log(body);
});
res.json(req.body); // both this and res.json(body) does not work
});
将res.json(req.body);
移动到回调函数中。
除了范围问题:它是异步的,因此在您的代码中它将在 res.json(req.body)
运行后很长时间内被调用。
app.get('/api/etsy/getListings', function(req, res) {
bEtsy.getAllListings(req, res, function(err, body) {
res.json(body);
//console.log(body);
});
});
一条更一般的建议(或两三条),除了手头的问题:
对我有帮助的是 "callback thinking" 几乎从不使用内联回调函数:只编写一层深的代码(当然还要为模块模式加上一层),避免回调地狱!命名所有回调并将它们全部写在同一(顶部)级别。
function allListingsReceived(err, body, res) {
res.json(body);
//console.log(body);
}
function getListings(req, res) {
// ASYNC
bEtsy.getAllListings(req, res, allListingsReceived);
}
//ASYNC
app.get('/api/etsy/getListings', getListings);
这使我能够更好地了解实际调用顺序。在这种情况下,当 getAllListings
被调用时,您知道它是异步的——在我自己的代码中,我添加了一个明确的注释(就像我在上面所做的那样)。所以我知道在异步函数将无法访问异步函数应该得到的任何东西之后我要写的任何东西。恕我直言,这样的评论 很重要 - 在 Javascript 中没有办法知道回调函数是否异步。通常是这样,但如果它是同步的并且您期望异步,您也可能会遇到麻烦!所以我认为最好把它写成注释(在整个项目中始终是完全相同的短字符串),一种形式化的代码注释。顺便说一句,这会导致另一个问题:当您编写接受回调函数的函数时,请确保它们 总是 同步或异步调用它,永远不要两种方式都调用(某些函数使用缓存值和能够立即 return 结果,而不是启动异步网络请求。
基本上,书面结构并没有反映这种风格的运行时情况 - 但这没关系,因为运行时情况无论如何都是完全灵活的(如果你想改变你使用的回调函数,或在两者之间添加另一个,您真的想转移大量代码行而不是仅仅交换名称吗?更不用说提高可重用性 )。这在更长的 callback-style 代码文件中比在多层深层嵌套的异步函数恕我直言中更容易阅读。除了模块模式,尽可能避免函数内部函数。
命名函数也更利于调试,堆栈跟踪更易于阅读。
注意:我的示例代码留下了一个未解决的问题:如果这是在模块(或 class)内,则这些将是内部函数,您可能必须确保正确的 context/scope(其中 this
指向,如果您从这些函数内部以这种方式访问 object 成员变量)。不过,当这些函数在原型上时,它的工作原理是一样的。所以这只是一个忽略这个附带问题的一般概念示例。
另一个注意事项:在编写此样式变量时,以前可通过闭包供内部函数使用 - 在本例中 res
- 现在必须在调用回调函数时作为函数参数提供。这增加了一些复杂性——但另一方面迫使您在自己的代码中创建干净的(呃)API。我个人不喜欢过度依赖闭包来传递参数。我太笨了,我更喜欢通过在其 header 中包含一个函数使用的所有参数来拥有一个干净的接口定义。显然我并不孤单,这是函数式编程最常被吹捧的优点之一 :) object 下的 object 属性也是用 "clean" 参数填充 header 的替代方法=15=]。我的小例子看起来有点"procedural",但它只能说明一点。当然,这属于模块化编程的更大范围。
嗨,我有一个非常简单(我认为)的 js 问题,我似乎被卡住了。 我正在尝试创建下面的路线。
从 bEtsy 函数中得到 console.logged 的是我希望在页面上显示的内容。但是 'body' 在该范围之外不可用。
app.get('/api/etsy/getListings',function(req, res){
bEtsy.getAllListings(req, res, function(err, body) {
// console.log(body);
});
res.json(req.body); // both this and res.json(body) does not work
});
将res.json(req.body);
移动到回调函数中。
除了范围问题:它是异步的,因此在您的代码中它将在 res.json(req.body)
运行后很长时间内被调用。
app.get('/api/etsy/getListings', function(req, res) {
bEtsy.getAllListings(req, res, function(err, body) {
res.json(body);
//console.log(body);
});
});
一条更一般的建议(或两三条),除了手头的问题:
对我有帮助的是 "callback thinking" 几乎从不使用内联回调函数:只编写一层深的代码(当然还要为模块模式加上一层),避免回调地狱!命名所有回调并将它们全部写在同一(顶部)级别。
function allListingsReceived(err, body, res) {
res.json(body);
//console.log(body);
}
function getListings(req, res) {
// ASYNC
bEtsy.getAllListings(req, res, allListingsReceived);
}
//ASYNC
app.get('/api/etsy/getListings', getListings);
这使我能够更好地了解实际调用顺序。在这种情况下,当 getAllListings
被调用时,您知道它是异步的——在我自己的代码中,我添加了一个明确的注释(就像我在上面所做的那样)。所以我知道在异步函数将无法访问异步函数应该得到的任何东西之后我要写的任何东西。恕我直言,这样的评论 很重要 - 在 Javascript 中没有办法知道回调函数是否异步。通常是这样,但如果它是同步的并且您期望异步,您也可能会遇到麻烦!所以我认为最好把它写成注释(在整个项目中始终是完全相同的短字符串),一种形式化的代码注释。顺便说一句,这会导致另一个问题:当您编写接受回调函数的函数时,请确保它们 总是 同步或异步调用它,永远不要两种方式都调用(某些函数使用缓存值和能够立即 return 结果,而不是启动异步网络请求。
基本上,书面结构并没有反映这种风格的运行时情况 - 但这没关系,因为运行时情况无论如何都是完全灵活的(如果你想改变你使用的回调函数,或在两者之间添加另一个,您真的想转移大量代码行而不是仅仅交换名称吗?更不用说提高可重用性 )。这在更长的 callback-style 代码文件中比在多层深层嵌套的异步函数恕我直言中更容易阅读。除了模块模式,尽可能避免函数内部函数。
命名函数也更利于调试,堆栈跟踪更易于阅读。
注意:我的示例代码留下了一个未解决的问题:如果这是在模块(或 class)内,则这些将是内部函数,您可能必须确保正确的 context/scope(其中 this
指向,如果您从这些函数内部以这种方式访问 object 成员变量)。不过,当这些函数在原型上时,它的工作原理是一样的。所以这只是一个忽略这个附带问题的一般概念示例。
另一个注意事项:在编写此样式变量时,以前可通过闭包供内部函数使用 - 在本例中 res
- 现在必须在调用回调函数时作为函数参数提供。这增加了一些复杂性——但另一方面迫使您在自己的代码中创建干净的(呃)API。我个人不喜欢过度依赖闭包来传递参数。我太笨了,我更喜欢通过在其 header 中包含一个函数使用的所有参数来拥有一个干净的接口定义。显然我并不孤单,这是函数式编程最常被吹捧的优点之一 :) object 下的 object 属性也是用 "clean" 参数填充 header 的替代方法=15=]。我的小例子看起来有点"procedural",但它只能说明一点。当然,这属于模块化编程的更大范围。