Dalam kode yang sedikit dikurangi ini, satu atau beberapa minggu pengamatan diunduh setiap minggunya dari API, dan digabungkan ke dalam rows dan diekspor ke CSV. Setidaknya itulah idenya. Apa yang sebenarnya terjadi adalah Uncaught (in promise) TypeError: Cannot read property 'toString' of undefined dimunculkan dalam fungsi (tidak ditampilkan) exportToCsv karena _promise didorong dari promiseArray ke rows keluar sebagai undefined. Apa yang saya lewatkan?

$("#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;
}
0
Jamie Bull 16 Maret 2017, 04:22

2 jawaban

Jawaban Terbaik

Janji bukanlah benda ajaib yang “menjadi” nilai yang berbeda ketika ditepati. Saat Anda melakukan rows.push(promiseArray[i]);, Anda mengumpulkan objek janji bukan hasil yang dikandungnya.

Untuk mengakses hasil yang telah atau akan dipenuhi oleh janji, Anda perlu menghubungkan panggilan balik .then(…) ke sana di mana Anda dapat mengakses hasilnya sebagai parameter. Untuk mengumpulkan hasil dari semua janji dalam larik, Anda menggunakan Promise.all, yang mengembalikan janji lain yang tidak hanya menunggu semua janji masukan tetapi juga memenuhi dengan larik nilai hasil mereka.

$("#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
Bergi 16 Maret 2017, 02:01

Anda dapat menerima hasil dari promise Anda di handler then:

Promise.all(promiseArray).then( function (results) { // Wait for all promises to resolve
    var rows = [headers].concat(results);
    exportToCsv( fileName, rows );
  })
1
rasmeister 16 Maret 2017, 01:35