【问题标题】:define outer scope variable inside function在函数内部定义外部范围变量
【发布时间】:2019-10-05 15:02:13
【问题描述】:

我正在为表单的字段服务器端(expressjs)之一构建验证并为此执行以下操作:

  1. 从json文件中读取数据

  2. 从中获取属性(数组)

  3. 检查它是否包含用户生成数组的每一个元素,仅此而已,例如:

[1,2,3,4,5]; (json array)
[1,2,3,4,5,6] (user generated array) //must return false

[1,2,3,4,5];
[1,3,4] //must return true;

[1,2,3,4,5];
[1,2,7] //must return false;

所以我使用这个代码:

const contains = (arr1, arr2) => {
  arr2.every(v => arr1.indexOf(v) !== -1)
}
var match;
fs.readFile('../tags.json', 'utf8', (err, data)=>{

  var JsonData = JSON.parse(data);
  var tagsArray = JsonData.tags;
  console.log(tagsArray)
  console.log(tags)
  if(tagsArray instanceof Array){
    console.log('tagsArray is array')
  }
  if(!contains(tagsArray, tags)){
    match = false
  }   
  else{
    match = true
  }
  console.log(match + ' blah1')

});

console.log(match + ' blah2')
if(match == false){
  return res.status(409).send({
    message: 'Do not provide your own tags'
  });
}

但它总是在fs.readFile 块内返回false,因为它在fs.readFile 块外返回未定义,所以这意味着包含函数返回未定义(我测试过)

那么这有什么线索呢? 谢谢!

【问题讨论】:

标签: javascript arrays node.js json express


【解决方案1】:

您可以使用 async/await

async function read(){
let data = await fs.readFile(<path>);
console.log(data); //You can use data everywhere within this scope
}

【讨论】:

    【解决方案2】:

    fs.readFile 是异步的,因此任何依赖于其结果(正在读取的文件)的代码都需要放在您的回调函数中。 (回调函数是(err, data) =&gt; { ... }部分。)

    console.log(match + 'blah2')if(match == false) { ... } 部分移动到回调内部(在 blah1 行之后)。

    您也可以查看async 或使用fs.readFileSync,这样可以避免使用回调函数。

    另一方面,您需要确保始终到达res.send() 行,即在您的情况下是match == true。否则当匹配为真时你的http请求不会返回。

    编辑:

    这是一个非常基本的 express 结构,主要是伪代码和 cmets,只是为了说明回调:

    app.post('/tags', (req, res) => {
    
      // your setup code here
    
      fs.readFile('../tags.json', 'utf8', (err, data) => {
    
        console.log('readFile has finished')
    
        // now you have heard back from readFile
        // check the err and send 500 if there was a problem
        // otherwise work with the file in the var data
    
        // any other db-related stuff also goes in here, which probably
        //   has its own callback you need to use
        db.save(data, (err) => {
          // db call is done, potentially with an error
          // Here you can use `res` to send http response
        })
        // !! again here the db is still doing its work
      })
    
      // !! anything you add here will be executed before readFile is done
      console.log('readFile is probably still at work')
    
    })
    

    我还应该指出,您希望contains 返回布尔值,即return arr2.every(...)

    【讨论】:

    • 如果我在回调函数中移动 if 语句会导致错误:发送后无法设置标题
    • 因为,我不是同步函数的忠实拥护者,因为它会阻塞线程,所以我想要异步解决方案,但顺便说一下,在这种情况下,哪个是最可取的(我知道它是可选的,但例如,如果您解决这个问题,您会使用一个)?我这么说是因为我第一次遇到这种问题
    • 标题错误可能是一个单独的问题。我可以通过将这 6 行移到回调中来使事情正常进行。回复:a/sync,你的一般方法很好。请参阅@eol 提供的链接,详细了解它的工作原理。
    • 是的,你可以,但我不能,因为这个函数在 router.post 里面,我在这个块之后发送状态码,所以它会导致错误
    • 是的,不要在回调之外发送状态码。
    猜你喜欢
    • 2021-08-18
    • 1970-01-01
    • 2014-05-29
    • 2021-08-20
    • 1970-01-01
    • 1970-01-01
    • 2012-10-14
    • 2011-06-01
    • 1970-01-01
    相关资源
    最近更新 更多