推送到javascript对象中的数组

时间:2018-09-04 16:37:33

标签: javascript arrays angularjs javascript-objects

功能v1执行不带错误,并且控制台日志显示不带响应数据的预期数组。但是,我试图通过将nysQueryReturn中的2个数组作为一个对象返回来简化生活:

功能v2 执行也没有错误,但是控制台日志显示

nysQueryReturn {sldlBills: Array(0), slduBills: Array(0)}
...空数组。

功能v1:按预期工作

function getBillData() {
  return getBills().
  then(function(response) {
    // save retrieved bill numbers
    var billData = response;
    var nysQueryReturn = [];

    // get NY State Leg data for each bill number
    billData.forEach(function(p) {

      // Assembly bill
      nysBillQuery(p.gsx$sessionyear.$t, p.gsx$assemblynum.$t).
      then(function(response){
        nysQueryReturn.push(response);
      });

      // Senate bill
      nysBillQuery(p.gsx$sessionyear.$t, p.gsx$senatenum.$t).
      then(function(response){
        nysQueryReturn.push(response);
      });
    });
    console.log('nysQueryReturn', nysQueryReturn);
    return nysQueryReturn;
  });
} // end of getBillData()

函数v2:空数组:(

function getBillData() {
  return getBills().
  then(function(response) {
    // save retrieved bill numbers
    var billData = response;
    var nysQueryReturn = {
      sldlBills: [],
      slduBills: []
    };

    // get NY State Leg data for each bill number
    billData.forEach(function(p) {

      // Assembly bill
      nysBillQuery(p.gsx$sessionyear.$t, p.gsx$assemblynum.$t).
      then(function(response){
        nysQueryReturn.sldlBills.push(response);
      });

      // Senate bill
      nysBillQuery(p.gsx$sessionyear.$t, p.gsx$senatenum.$t).
      then(function(response){
        nysQueryReturn.slduBills.push(response);
      });
    });
    console.log('nysQueryReturn', nysQueryReturn);
    return nysQueryReturn;
  });
} // end of getBillData()

我已经在stackoverflow上找到了"array of arrays""array of objects"的几个示例,但是我看不到如何将这些答案重新用于我的“数组对象”场景。我所缺少的任何想法/指针/解释都将受到热烈欢迎。

谢谢您的时间。

编辑:

k,我发现enter link description here,这似乎表明我“做对了”。换个角度看,Chrome Dev Tools控制台报告这两个数组是“空”的,但是展开时它们包含了预期的信息。尽管如此,我实际上不能在没有得到nysQueryReturn.sldlBills[0].basePrintNo的情况下通过TypeError: Cannot read property 'basePrintNo' of undefined来访问带有android/build.gradle的数组元素,而且我一生都无法弄清楚为什么为什么< / em>。

我没有得到什么?

2 个答案:

答案 0 :(得分:1)

我假设您了解arrow functions以及如何正确使用它们。我还将假设您了解letconst。这些都不是必需的,它们只是使事情变得更漂亮。您可以将所有箭头功能(在下面的示例中)替换为普通功能,并将所有letconst声明替换为var声明。

您的最终结果应类似于以下内容:

function getBillData() {
  return getBills().then((billData) => {
    const nysQueryReturn = {
      sldlBills: [],
      slduBills: []
    };

    // This should look familiar, it returns a Promise.  This
    // Promise first loads the Assembly bill then adds the result
    // to the appropriate array in nysQueryReturn object.
    const loadAssemblyBill = (bill) => {
      return nysBillQuery(bill.gsx$sessionyear.$t, bill.gsx$assemblynum.$t).then((sldlBill) => {
        nysQueryReturn.sldlBills.push(sldlBill);
      });
    };

    // This should look familiar, it returns a Promise.  This
    // Promise first loads the Senate bill then adds the result to
    // the appropriate array in nysQueryReturn object.
    const loadSenateBill = (bill) => {
      return nysBillQuery(bill.gsx$sessionyear.$t, bill.gsx$senatenum.$t).then((slduBill) => {
        nysQueryReturn.slduBills.push(slduBill);
      });
    };

    // First exciting thing: Let's map each bill to a 2 workers
    // that will load the important information that we will add to
    // nysQueryReturn.
    const workers = [];

    billData.forEach((bill) => {
      workers.push(loadAssemblyBill(bill));
      workers.push(loadSenateBill(bill));
    });

    // Return a Promise that will wait for all the workers to
    // finish.
    return Promise.all(workers).then(() => nysQueryReturn);
  });
}

您没有看到预期的结果,因为您没有等待结果加载。实际上,如果您设置了超时并在以后的某个时间检查结果,您将看到阵列已填充。

让我们将nysQueryReturn视为一个容纳所有sldlBillsslduBills的盒子,将Promises当作工作人员,并将调用getBillData()的代码作为您的客户。使用getBillData()的v2,您

  1. 找到所有账单。
  2. 创建了nysQueryReturn
  3. 雇用了一些工人,并告诉他们该怎么做。
  4. 把盒子交给客户。

不幸的是,您没有等到您的工人完成工作,才把盒子交给客户。不用说,您的客户很困惑,只是假装他们得到了他们想要的东西。

有了新的实现,您

  1. 找到所有账单。
  2. 创建了nysQueryReturn
  3. 雇用了一些工人,并告诉他们该怎么做。
  4. 请您的员工将您发现的内容提供给您。
  5. 把盒子交给客户。

您通过维护workers的列表来等待工作人员完成工作,然后等待其中的all()Promise.all())人告诉您他们已经完成工作并将结果添加到nysQueryReturn框。完成所有步骤后,您就可以向客户提供所有结果(.then(() => nysQueryReturn)

请记住,每次使用Promise(任何具有.then()方法的东西)时,您都在执行普通程序流程之外的操作。 JS将不等待该流程完成再继续其原始流程。从图片上看,这看起来像:

___________                     ____________                                ____________
|  Flow 1 |                     |  Flow 2  |                                |  Flow 3  |
-----------                     ------------                                ------------

billData.forEach(/* ... */);
console.log(/*...*/);
return nysQueryReturn;
                                nysQueryReturn.sldlBills.push(/*...*/);
                                                                            nysQueryReturn.slduBills.push(/*...*/)

要等待新流程结束,您必须通过将回调传递给.then()来显式地等待它。

答案 1 :(得分:0)

Promise是异步函数,因此请不要逐行运行。我建议您阅读https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise,以了解Promise是如何工作的。 您可以尝试以下代码:使用map返回promise,然后使用Promise.all等待全部完成。

function getBillData() {
    return getBills()
    .then(function (response) {
        var billData = response;
        var nysQueryReturn = {
            sldlBills: [],
            slduBills: []
        };

        prs = billData.map(function (p) {
            return nysBillQuery(p.gsx$sessionyear.$t, p.gsx$assemblynum.$t)
                .then(function (res) {
                    nysQueryReturn.sldlBills.push(res);
                    return nysBillQuery(p.gsx$sessionyear.$t, p.gsx$senatenum.$t);
                })
                .then(function (res) {
                    nysQueryReturn.slduBills.push(res);
                });
            });

        return Promise.all(prs).then(function () {
            return nysQueryReturn
        });

    });
} // end of getBillData()