【问题标题】:Variable undefined outside function scope despite being assigned?尽管分配了变量,但在函数范围之外未定义?
【发布时间】:2019-07-25 01:48:43
【问题描述】:

问题

我在使用 MERM 应用程序时遇到问题,其中在整个函数的主体中声明的变量被分配给子函数,但是,每当我尝试在末尾操作/显示此变量时整个函数,它返回一个“未定义”。

代码

getSimilarCasesFromID: function(req, res, next) {
    let queryString = "id::"+req.params.id; 
    let params = {
        'query': queryString,
        'environment_id':environmentId,
        'collection_id': collectionId,
        'configuration_id': configurationId,
        return: 'enriched_text'
    }

    let filterStrArr = [];
    const FILTER_CONCEPT = "enriched_text.concepts.text:";
    let filterStr ="";

    discovery.query(params, (error, results) => {
        if (error) {
            next(false, err, []);
        } else {
            let conceptSize = results.results[0].enriched_text.concepts.length;
            let concepts = {};
            for (let i = 0; i < conceptSize; i++) {
                concepts[i] = { 
                    text: results.results[0].enriched_text.concepts[i].text,
                    relevance: results.results[0].enriched_text.concepts[i].relevance
                 };

                filterStrArr[i] = FILTER_CONCEPT + concepts[i].text;
            }

            filterStr = filterStrArr.join(",");
            console.log(filterStr);
            //1. Works and displays---------------
        }
    });

    console.log("FullString (2.)"+filterStr);
    //2. Undefined????????????????????------------

    next(true, [], []);
},

我指的是第 (1.) 和 (2.) 行。我不知道我是否遗漏了什么,并犯了一个愚蠢的小错误。

服务器上的输出:

有趣的是,如图 1 所示,FullString (2.) 出现在第 (1.) 行之前。这可能是由于 Watson Discovery 的响应时间造成的吗?请记住该服务位于澳大利亚悉尼?如果是这样,还有其他人有这方面的经验吗?

【问题讨论】:

    标签: node.js reactjs express ibm-watson watson-discovery


    【解决方案1】:

    discovery.query 是一个异步函数,因此变量filterStr 在到达回调之前不会被定义。您需要在discovery.query 的回调中使用filterStr 或在try/catch 块中使用async/awaitreturn results

    异步函数的工作方式是允许它在不中断线程的情况下执行。所以这就是为什么console.log(2.) 被执行,然后一段时间后,console.log(1.) 在回调中执行(由于函数是asynchronous,到达回调需要一些时间)。您正在尝试做事情synchronously,为此,您需要重构您的代码。 Click here 了解有关异步和同步执行的更多信息。

    回调内

    getSimilarCasesFromID: function(req, res, next) {
      const queryString = "id::"+req.params.id; 
      const params = {
        'query': queryString,
        'environment_id':environmentId,
        'collection_id': collectionId,
        'configuration_id': configurationId,
        return: 'enriched_text'
      };
    
      const filterStrArr = [];
    
      const FILTER_CONCEPT = "enriched_text.concepts.text:";
    
      discovery.query(params, (error, results) => {
        if (error) {
          next(false, err, []);
        } else {
          let filterStr ="";
    
          const conceptSize = results.results[0].enriched_text.concepts.length;
    
          let concepts = {};
          for (let i = 0; i < conceptSize; i++) {
            concepts[i] = { 
              text: results.results[0].enriched_text.concepts[i].text,
              relevance: results.results[0].enriched_text.concepts[i].relevance
            };
    
            filterStrArr[i].push(FILTER_CONCEPT + concepts[i].text);
          }
    
          filterStr = filterStrArr.join(",");
          console.log(filterStr);
    
          // utilize filterStr here
    
          next(true, [], []);
        }
      });
    },
    

    async/await

    getSimilarCasesFromID: async function(req, res, next) {
      const queryString = "id::"+req.params.id; 
      const params = {
        'query': queryString,
        'environment_id':environmentId,
        'collection_id': collectionId,
        'configuration_id': configurationId,
        return: 'enriched_text'
      }
    
      const filterStrArr = [];
    
      const FILTER_CONCEPT = "enriched_text.concepts.text:";
    
      let filterStr ="";
    
      try {
        const results = await discovery.query(params);
    
        const conceptSize = results.results[0].enriched_text.concepts.length;
    
        let concepts = {};
        for (let i = 0; i < conceptSize; i++) {
          concepts[i] = { 
            text: results.results[0].enriched_text.concepts[i].text,
            relevance: results.results[0].enriched_text.concepts[i].relevance
          };
    
          filterStrArr[i].push(FILTER_CONCEPT + concepts[i].text);
        }
    
        filterStr = filterStrArr.join(",");
        console.log(filterStr);
    
        // utilize filterStr here
    
        next(true, [], []);       
    
      } catch(err) {
         next(false, err, []);
      }
    },
    

    【讨论】:

    • 感谢您的帮助,马特!我必须承认,我最初对与“同步”和“异步”函数有关的术语感到困惑。您的解释非常有帮助。
    【解决方案2】:

    discovery.query() 有两个属性,
    1 - 参数
    2 - 函数(也称为回调)

    discover.query() 被执行,但在回调执行之前返回,
    下一个 console.log("FullString (2.)"+filterStr);被执行
    最后执行回调。

    您需要在回调中采取所需的操作。

    这很痛苦,但这就是 JavaScript 的工作原理。更准确地说,discovery.query() 是如何工作的。更糟糕的是,当你有嵌套的回调时,它会变得非常混乱并且有一个名字:“回调地狱”。这个问题的现代解决方案是 promises 和 async await。

    祝你好运

    【讨论】:

    • 感谢您的帮助!
    猜你喜欢
    • 2023-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-05
    • 1970-01-01
    相关资源
    最近更新 更多