【问题标题】:Uncaught (in promise) TypeError: Cannot read property 'length' of undefined at promiseKey.thenUncaught (in promise) TypeError: Cannot read property 'length' of undefined at promiseKey.then
【发布时间】:2018-01-24 00:38:38
【问题描述】:

我正在尝试从 Promise 返回一组推送的数据,然后循环多次以填充所有数据。例如,我有一个品牌列表和一个接收品牌参数并返回一组推送数据的函数。

var datasetarr = [];
brandlist = ['Bh', 'Ruffles'];

let promiseKey = new Promise((resolve, reject) => {
    for(var i = 0; i < brandlist.length; i++){
        datasetarr = populateData(brandlist[i], datasetarr);
    }
    resolve(datasetarr);
});

promiseKey.then((arr) => {
    console.log('complete promise');
    for(var i = 0; i < arr.length; i++){
        console.log(arr[i].date + ' ' + arr[i].total);
    }
});

错误信息是

Uncaught (in promise) TypeError: Cannot read property 'length' of undefined
    at promiseKey.then

我的数据提取没有问题,因为我设法打印出了详细信息。这意味着承诺没有正确解决。这是从承诺返回数组的正确方法吗?我不确定哪一部分是错的。

【问题讨论】:

  • promise 未定义
  • 是的,我也没有找到承诺。
  • 注意,let promiseKey = ... 将立即解析为undefined,因为populateData 不会返回任何内容
  • @JaromandaX “我对您遇到的错误感到惊讶” 请参阅原始帖子。 promise 未定义。编辑后datasetarr 仍然未定义在.then()
  • 不,我明白为什么datasetarrundefined,因为populateData 返回undefined - 并且populateData 将第二次失败,因为datasetarr.push 将失败为@987654336 @ 参数将是 undefined 第二次

标签: javascript asynchronous promise resolve


【解决方案1】:

首先,您的 populateData 需要返回一个 Promise - 在这种情况下,它将是在 data.forEach 中创建的已解析的承诺数组

var brandlist = ['Bh', 'Ruffles'];

let promiseKey = Promise.all(brandlist.map(brand => populateData(brand)))
.then(results => [].concat(...results)); // flatten the array of arrays

promiseKey.then((arr) => {
    console.log('complete promise');
    for(var i = 0; i < arr.length; i++){
        console.log(arr[i].date + ' ' + arr[i].total);
    }
});

function populateData(brand, datasetarr) {
    console.log('go in');
    var query;// = // query by brand parameter
    return query.once('value').then(data => {
        var promises = [];
        data.forEach(snapshot => {
            // get each receipt item details

            // get receipt details by receipt ID
            var query;// = // query receipts
            promises.push(query.once('value').then(data => { 
                // removed code
                // managed to print out here so data fetching is not a problem
                console.log(brand + ' ' + date + ' ' + itemTotal);
                return {date: date, total: itemTotal};
            })); 
        }); 
        return Promise.all(promises);
    });
}

或者,使用我在this answer a week ago 中给你的snapshotToArray 函数

const snapshotToArray = snapshot => {
    const ret = [];
    snapshot.forEach(childSnapshot => {
        ret.push(childSnapshot);
    });
    return ret;
};

function populateData(brand, datasetarr) {
    console.log('go in');
    var query;// = // query by brand parameter
    return query.once('value').then(data => Promise.all(snapshotToArray(data).map(snapshot => {
        // get each receipt item details

        // get receipt details by receipt ID
        var query;// = // query receipts
        return query.once('value').then(data => { 
            // removed code
            // managed to print out here so data fetching is not a problem
            console.log(brand + ' ' + date + ' ' + itemTotal);
            return {date: date, total: itemTotal};
        }); 
    }))); 
}

【讨论】:

  • 不,你没有误解任何东西。这位用户一周前问了一个更复杂的问题——我希望他们在答案中使用一些“技术”,但显然他们没有,因为这段代码几乎和代码一样缺乏理解上周
  • 上周有一些条件,导致 undefined 数组条目,所以进行了这种讨厌的过滤:p 我说讨厌,因为我认为我过度使用 .filter 老实说
【解决方案2】:

虽然可以在任何地方使用您 push 的全局 datasetarray 变量,但我建议不要这样做。相反,编写一个方法getData,它返回(一个承诺)一个数组,并在多次调用之后(每个品牌一次)将它们连接在一起。

const brandlist = ['Bh', 'Ruffles'];
const promiseKey = Promise.all(brandlist.map(getData)).then(arrays => [].concat(...arrays));
promiseKey.then(arr => {
    console.log('complete promise');
    for (const item of arr)
        console.log(item.date + ' ' + item.total);
});

function getData(brand) { // no array parameter!
    console.log('go in');
    const query = …; // query by brand parameter
    return query.once('value').then(data => {
        const promises = toArray(data).map(snapshot => {
        const query = …; // get receipt item details by receipt ID
        return query.once('value').then(data => { 
            …
            return {date: date, total: itemTotal}; // don't push, just return the result
        });
        return Promise.all(promises); // resolves with an array of results
    }); // resolves with that same result array
}
function toArray(forEachable) {
    const arr = [];
    forEachable.forEach(x => { arr.push(x); });
    return arr;
}

【讨论】:

  • 它告诉我 data.map 不是这一行的函数: const promises = data.map(snapshot => {
  • 我认为你中了data.map 陷阱 - 数据不是数组:p
  • 我更喜欢你的toArray 函数——因为它的名字是通用的:p
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-12
  • 2021-09-20
  • 2021-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多