功能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>。
我没有得到什么?
答案 0 :(得分:1)
我假设您了解arrow functions以及如何正确使用它们。我还将假设您了解let
和const
。这些都不是必需的,它们只是使事情变得更漂亮。您可以将所有箭头功能(在下面的示例中)替换为普通功能,并将所有let
和const
声明替换为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
视为一个容纳所有sldlBills
和slduBills
的盒子,将Promises当作工作人员,并将调用getBillData()
的代码作为您的客户。使用getBillData()
的v2,您
nysQueryReturn
框不幸的是,您没有等到您的工人完成工作,才把盒子交给客户。不用说,您的客户很困惑,只是假装他们得到了他们想要的东西。
有了新的实现,您
nysQueryReturn
框您通过维护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()