【问题标题】:Why is no value returned from my Promise?为什么我的 Promise 没有返回值?
【发布时间】:2017-03-16 10:01:09
【问题描述】:

在这个略微简化的代码中,每周从 API 下载一周或多周的观察结果,并汇总到 rows 并导出为 CSV。至少是这样的想法。实际发生的是Uncaught (in promise) TypeError: Cannot read property 'toString' of undefined 在(未显示的)exportToCsv 函数中引发,因为从promiseArray 推送到rows_promiseundefined 的形式出现。我错过了什么?

$("#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;
}

【问题讨论】:

  • 我认为你的主要问题是_promise 不是一个承诺,而是一个deferred object。你需要promiseArray.push(_promise.promise)。你为什么使用Q原生Promise
  • 来自this answer to an earlier question。我对 jQuery 和 promises 完全陌生

标签: javascript jquery promise q


【解决方案1】:

promise 不是一个神奇的对象,当它被解析时“变成”一个不同的值。当你在做rows.push(promiseArray[i]); 时,你收集的是promise 对象而不是它们包含的结果。

要访问承诺已经或将要实现的结果,您需要将.then(…) 回调链接到它,您可以在其中将结果作为参数访问。要从数组中的所有 Promise 中收集结果,请使用 Promise.all,它会返回另一个 Promise,它不仅等待所有输入 Promise,而且还使用它们的结果值数组来实现。

$("#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;
}

【讨论】:

    【解决方案2】:

    您可以在then 处理程序中收到您的承诺的结果:

    Promise.all(promiseArray).then( function (results) { // Wait for all promises to resolve
        var rows = [headers].concat(results);
        exportToCsv( fileName, rows );
      })
    

    【讨论】:

      猜你喜欢
      • 2021-01-11
      • 2021-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-29
      • 1970-01-01
      • 2011-08-09
      相关资源
      最近更新 更多