为什么我的 Promise 没有返回值?
Why is no value returned from my Promise?
在这个略微简化的代码中,每周从 API 下载一周或多周的观察结果,然后汇总到 rows
并导出为 CSV。至少那是想法。实际发生的是 Uncaught (in promise) TypeError: Cannot read property 'toString' of undefined
在(未显示)exportToCsv
函数中被引发,因为从 promiseArray
推到 rows
的 _promise
作为undefined
。我错过了什么?
$("#downloadBtn").click(function() {
weeks = getWeeks(startDate.val(), endDate.val()); // array like [[startDay1, endDay1], [startDay2, endDay2], ...]
// start downloading the data
var promiseArray = [];
for (i=0; i< weeks.length; i++) {
var _promise = Q.defer();
fetchDataWeek( weeks[i][0], weeks[i][1], _promise );
promiseArray.push(_promise) // Push this promise into the array
}
Promise.all(promiseArray).then( function () { // Wait for all promises to resolve
var rows = [headers];
for (i=0; i < promiseArray.length; i++) {
rows.push(promiseArray[i]);
}
exportToCsv( fileName, rows );
})
});
function fetchDataWeek( startDay, endDay, _promise ) {
url = "https://api" + startDay + endDay + ".json";
$.ajax({
url: url,
success: function(result){
var weekRows = parseHistory(result);
_promise.resolve(weekRows);
},
error: function (error) {
_promise.reject(error) // rejecting it in case of error
}
});
}
// Extract all data from a query response
function parseHistory(data) {
var weekRows = [];
var days = data.history.days;
for (var i = 0; i < days.length; i++) {
dayRows = formatDay( days[i] );
for (var j= 0; j < dayRows.length; j++) {
weekRows.push(dayRows[j]);
}
}
return weekRows;
}
您可以在 then
处理程序中收到您承诺的结果:
Promise.all(promiseArray).then( function (results) { // Wait for all promises to resolve
var rows = [headers].concat(results);
exportToCsv( fileName, rows );
})
Promise 不是一个神奇的对象,它在解析时 "becomes" 具有不同的值。当您执行 rows.push(promiseArray[i]);
时,您收集的是 promise 对象而不是它们包含的结果。
要访问承诺已经或将要实现的结果,您需要将 .then(…)
回调链接到它,您可以在其中将结果作为参数访问。要从数组中的所有承诺中收集结果,您可以使用 Promise.all
,这是另一个承诺,它 returns 不仅等待所有输入承诺,而且还用其结果值的数组来实现。
$("#downloadBtn").click(function() {
var weeks = getWeeks(startDate.val(), endDate.val());
// start downloading the data
var promiseArray = weeks.map(function(week) { // map is simpler than a loop with `push`
return fetchDataWeek( week[0], week[1] );
})
Promise.all(promiseArray).then( function(results) { // Wait for all promises to resolve
var rows = [headers].concat(results);
exportToCsv( fileName, rows );
})
});
function fetchDataWeek( startDay, endDay, _promise ) {
var url = "https://api" + startDay + endDay + ".json";
var jQpromise = $.ajax({
url: url
});
var qPromise = Q(jQpromise);
return qPromise.then(parseHistory);
}
function parseHistory(data) {
var weekRows = [];
var days = data.history.days;
for (var i = 0; i < days.length; i++) {
var dayRows = formatDay( days[i] );
for (var j= 0; j < dayRows.length; j++) {
weekRows.push(dayRows[j]);
}
}
return weekRows;
}
在这个略微简化的代码中,每周从 API 下载一周或多周的观察结果,然后汇总到 rows
并导出为 CSV。至少那是想法。实际发生的是 Uncaught (in promise) TypeError: Cannot read property 'toString' of undefined
在(未显示)exportToCsv
函数中被引发,因为从 promiseArray
推到 rows
的 _promise
作为undefined
。我错过了什么?
$("#downloadBtn").click(function() {
weeks = getWeeks(startDate.val(), endDate.val()); // array like [[startDay1, endDay1], [startDay2, endDay2], ...]
// start downloading the data
var promiseArray = [];
for (i=0; i< weeks.length; i++) {
var _promise = Q.defer();
fetchDataWeek( weeks[i][0], weeks[i][1], _promise );
promiseArray.push(_promise) // Push this promise into the array
}
Promise.all(promiseArray).then( function () { // Wait for all promises to resolve
var rows = [headers];
for (i=0; i < promiseArray.length; i++) {
rows.push(promiseArray[i]);
}
exportToCsv( fileName, rows );
})
});
function fetchDataWeek( startDay, endDay, _promise ) {
url = "https://api" + startDay + endDay + ".json";
$.ajax({
url: url,
success: function(result){
var weekRows = parseHistory(result);
_promise.resolve(weekRows);
},
error: function (error) {
_promise.reject(error) // rejecting it in case of error
}
});
}
// Extract all data from a query response
function parseHistory(data) {
var weekRows = [];
var days = data.history.days;
for (var i = 0; i < days.length; i++) {
dayRows = formatDay( days[i] );
for (var j= 0; j < dayRows.length; j++) {
weekRows.push(dayRows[j]);
}
}
return weekRows;
}
您可以在 then
处理程序中收到您承诺的结果:
Promise.all(promiseArray).then( function (results) { // Wait for all promises to resolve
var rows = [headers].concat(results);
exportToCsv( fileName, rows );
})
Promise 不是一个神奇的对象,它在解析时 "becomes" 具有不同的值。当您执行 rows.push(promiseArray[i]);
时,您收集的是 promise 对象而不是它们包含的结果。
要访问承诺已经或将要实现的结果,您需要将 .then(…)
回调链接到它,您可以在其中将结果作为参数访问。要从数组中的所有承诺中收集结果,您可以使用 Promise.all
,这是另一个承诺,它 returns 不仅等待所有输入承诺,而且还用其结果值的数组来实现。
$("#downloadBtn").click(function() {
var weeks = getWeeks(startDate.val(), endDate.val());
// start downloading the data
var promiseArray = weeks.map(function(week) { // map is simpler than a loop with `push`
return fetchDataWeek( week[0], week[1] );
})
Promise.all(promiseArray).then( function(results) { // Wait for all promises to resolve
var rows = [headers].concat(results);
exportToCsv( fileName, rows );
})
});
function fetchDataWeek( startDay, endDay, _promise ) {
var url = "https://api" + startDay + endDay + ".json";
var jQpromise = $.ajax({
url: url
});
var qPromise = Q(jQpromise);
return qPromise.then(parseHistory);
}
function parseHistory(data) {
var weekRows = [];
var days = data.history.days;
for (var i = 0; i < days.length; i++) {
var dayRows = formatDay( days[i] );
for (var j= 0; j < dayRows.length; j++) {
weekRows.push(dayRows[j]);
}
}
return weekRows;
}