【问题标题】:Javascript class returning different values in console.logJavascript 类在 console.log 中返回不同的值
【发布时间】:2016-12-11 10:44:12
【问题描述】:

我有以下课程(此处删除了不必要的细节以使其更具可读性):

class CollectionManager {
constructor(){
    this.collectionList = {};
}
initialize(collections){
    ...
}
populate(){
    var collectionObjs = Object.keys(this.collectionList).map(function(key){
        return collectionManager.collectionList[key];
    });
    return Promise.all(collectionObjs.map(function(collection){
        collection.populateVideos();
    }));
}
}

.

class Collection {
constructor(data){
    this.collectionInfo = data;
    this.videoArray = [];
}
populateVideos(){
    var collectionKey = this.collectionInfo.COLLECTIONID;
    var vChannels = Object.keys(this.collectionInfo.channels);
    return Promise.all(vChannels.map(requestVideos))
        .then(function (results) {
            var videoIdArray = [];
            return videoIdArray = [].concat.apply([], results);
        }).then(function(arrVideoIds){
            var groups = [];
            for (var i = 0; i < arrVideoIds.length; i += 50) {
                groups.push(arrVideoIds.slice(i, i + 50));
            }
            return groups;
        }).then(function(chunkedArrVideoIds){
            return Promise.all(chunkedArrVideoIds.map(requestVideoData)).then(function (results) {
                var videoTileArray = [].concat.apply([], results);
                collectionManager.collectionList[collectionKey].videoArray = videoTileArray;
                return videoTileArray;
            });
        });
}
displayCollection(){
    console.log(this.collectionInfo.COLLECTIONID);
    console.log(collectionManager.collectionList);
    console.log(collectionManager.collectionList[1]);
    console.log(collectionManager.collectionList[1].videoArray);

我把这些类称为任何正常的承诺。

collectionManager.populate().then(
    function(){
        collectionManager.displayCollections()
    }
); 

现在我的问题是,当我调用此代码并读取控制台上的内容时,第四个控制台日志中的 videoArray 完全为空。 collectionManager.collectionList[1] 包含一个完整的对象,它有一个长度为 100 的 videoArray,我的所有视频都在其中。但是如果我打电话给collectionManager.collectionList[1].videoArray 它是空的,就像它没有被填满一样。据我所知,那些应该调用同一个确切的地方,但它给出了不同的结果。

有人看到我哪里搞砸了吗?

【问题讨论】:

  • in collectionObjs.map - 应该是 return collection.populateVideos(); - 否则你的 .map 将生成一个 undefined 数组 - 这将立即解决
  • .then(function (results) { var videoIdArray = []; return videoIdArray = [].concat.apply([], results); - 似乎多余 - 不只是返回结果数组,而且绝对不需要videoIdArray
  • @Jaromanda 添加 return collection.populateVideos() 解决了这个问题。承诺一直是我一直在努力的事情。我猜在响应到达之前承诺正在解决,所以控制台日志在 videoArray 更新之前记录?谢谢您的帮助!至于冗余:我将 arrVideoIds 分成 50 个块,这样我就可以通过他们的 api 向 Youtube 发出请求。我得到了一堆 50 长度的数组,所以我将它们连接在一起。
  • 啊啊啊,因为 results 是一个数组数组!! var videoIdArray = [] 仍然是多余的,你可以在 ES6 中只使用 .then(results=&gt; [].concat.apply([], results)) - 这是 .then(function(results) { return [].concat.apply([], results); })

标签: javascript arrays promise es6-promise


【解决方案1】:

populate 函数中,您的 Promise.all ... 映射返回一个未定义数组,Promise.all 将立即解决该数组

你应该这样做

populate(){
    var collectionObjs = Object.keys(this.collectionList).map(function(key){
        return collectionManager.collectionList[key];
    });
    return Promise.all(collectionObjs.map(function(collection){
        return collection.populateVideos();
    }));
}

但是,当您使用 Class - 您已经在使用更现代的 javascript

所以

populate(){
    var collectionObjs = Object.keys(this.collectionList).map(key => collectionManager.collectionList[key]);
    return Promise.all(collectionObjs.map(collection => collection.populateVideos()));
}

可以接受

顺便说一句,您的class Collection 也可以使用箭头函数(在我看来)变得更简洁,并使用更好的承诺链接

class Collection {
    constructor(data) {
        this.collectionInfo = data;
        this.videoArray = [];
    }
    populateVideos() {
        var collectionKey = this.collectionInfo.COLLECTIONID;
        var vChannels = Object.keys(this.collectionInfo.channels);
        return Promise.all(vChannels.map(requestVideos))
        .then(results => [].concat.apply([], results))
        .then(arrVideoIds => {
            var groups = [];
            for (var i = 0; i < arrVideoIds.length; i += 50) {
                groups.push(arrVideoIds.slice(i, i + 50));
            }
            return groups;
        )
        .then(chunkedArrVideoIds => Promise.all(chunkedArrVideoIds.map(requestVideoData)))
        .then(function(results) {
            var videoTileArray = [].concat.apply([], results);
            collectionManager.collectionList[collectionKey].videoArray = videoTileArray;
            return videoTileArray;
        });
    }
    displayCollection() {
        console.log(this.collectionInfo.COLLECTIONID);
        console.log(collectionManager.collectionList);
        console.log(collectionManager.collectionList[1]);
        console.log(collectionManager.collectionList[1].videoArray);
    }
}

【讨论】:

    【解决方案2】:

    我会避免使用 console.log() 进行调试,除非你真的想要让自己受挫。这可能是一个简单的 console.log() 行为不符合您预期的问题。相反,我建议在displayCollection() 中添加一个调试器语句。您所要做的就是将行 debugger; 添加到该函数的代码中,并在运行时打开 chrome 开发工具。执行将在该行停止,并允许您使用 chrome 开发工具(或您正在使用的任何浏览器的开发工具)检查应用程序状态。根据您那里的四个打印语句,我认为可能只是它没有按您的预期打印。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-03
      • 2013-08-17
      • 2013-05-10
      相关资源
      最近更新 更多