在另一个方法中,如何使用一个方法中嵌套函数返回的值?

时间:2019-04-20 19:22:37

标签: javascript json ajax constructor

我有一个构造函数,最后应该返回几个方法。目前,我很难理解如何使用

中的值
var info = JSON.parse(xhr.responseText);
方法中的

,称为getNames。如果将这两种方法合而为一,则它可以工作,因此代码本身也可以工作,唯一的问题是传递变量。

function TestConstructor(url) {
  var newObject = {};
  this.newObject = newObject;

构造函数中的第一个方法:

  newObject.load = function () {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "http://notarealurl.com/104857.json");
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4 && xhr.status === 200) {
        var info = JSON.parse(xhr.responseText);
        return info;
      }
     };
     xhr.send();
   };

构造函数中的第二种方法:

 newObject.getNames = function (info) {
   var kommuner = info.elements;
   var result = [];
   for (i = 0; i < Object.keys(kommuner).length; i++) {
      result.push(Object.keys(kommuner)[i]);
      }
   return result;
 };

return newObject;
}

当我尝试

console.log(newObject.getNames(info)); 

我收到错误消息

Uncaught TypeError: Cannot read property 'elements' of undefined
at Object.TestConstructor.newObject.getNames 

很抱歉,如果之前曾问过类似的问题,我看了几眼却不了解如何解决我的问题。我还尝试查看了回调函数,但是我很难理解它在我的情况下是如何工作的。任何帮助表示赞赏,谢谢:)

1 个答案:

答案 0 :(得分:1)

我认为,您正在寻找的行为是将“信息”存储在构造的对象本地的变量中,然后从第二种方法访问该变量。因此,为什么不将var info = null;放在构造函数中呢?然后,在解析数据后,将其分配给该变量(即删除var)。而且,您不必使用参数info,而只需使用该局部变量即可。

function TestConstructor(url) {
  var newObject = {};
  var info; // <-- local variable available to both functions.
  this.newObject = newObject;

  newObject.load = function () {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "http://notarealurl.com/104857.json");
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4 && xhr.status === 200) {
        info = JSON.parse(xhr.responseText); // <-- assign result to local variable
      }
    };
    xhr.send();
  };

  newObject.getNames = function() { // <-- no argument here
    var kommuner = info.elements; // <-- instead, use local variable
    var result = [];
    for (i = 0; i < Object.keys(kommuner).length; i++) {
      result.push(Object.keys(kommuner)[i]);
    }
    return result;
  };

  return newObject;
}

但是,这不是一个非常干净的解决方案。取而代之的是,正如SomePerformance建议的那样,您应该使用Promise模式异步提供数据,因为您目前尚不知道load调用实际上何时完成。因此,当您调用info时,getNames甚至可能没有初始化。

基于承诺的解决方案可能如下所示:

    function TestConstructor() {
      var newObject = {},
          info;

      newObject.load = function () {
        var p = new Promise(function(resolve, reject) {
          var xhr = new XMLHttpRequest();
          xhr.open("GET", "http://notarealurl.com/104857.json");
          xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
              if (xhr.status === 200) { // <-- call succeeded, parse result
                info = JSON.parse(xhr.responseText); // <-- assign result to local variable
                resolve(info); // <-- resolve promise with the result
              } else {
                reject(); // <-- call failed, reject the promise
              }
            }
          };
          xhr.send();
        });
        return p;
      };

      newObject.getNames = function() { // <-- no argument here
        var kommuner = info.elements; // <-- instead, use local variable
        var result = [];
        for (i = 0; i < Object.keys(kommuner).length; i++) {
          result.push(Object.keys(kommuner)[i]);
        }
        return result;
      };

      return newObject;
    }

    var myObj = new TestConstructor('');
    myObj.load().then(function() {
      var names = myObj.getNames();
      // do something with the result.
      console.log(names);
    }).catch(function() {
      // handle error graciously.
      console.warn('Failed');
    });

相关问题