为什么array.map不会改变任何东西?

时间:2018-12-29 14:48:58

标签: javascript arrays node.js

我正在尝试格式化从YouTube Data API v3获得的数据,但是我无法对其进行任何更改。

const videoIds = youtubeResponse.items.map(item => item.id);
VideoRepo.getById(videoIds, (err, videos) => {
    /* 
    videos is an array of objects that contain youtube videos from YT API and MongoDB(mongoose)
    */
    console.log(videos.map((v) => {
        v.time = moment(v.time).fromNow();
        v.duration = moment('1900-01-01 00:00:00').seconds(v.duration).format('HH:mm:ss');
        return v;
    }));
});

VideoRepo类:

  static getById(id, callback) {
    if (Array.isArray(id)) {
      // Multiple ids were specified
      async.waterfall([
        (next) => {
          // Get existing videos' data
          Video.find({ _id: { $in: id } }).select('-__v').sort({ createdAt: 1 }).exec((err, data) => {
            if (err) return next(err);
            next(null, data);
          });
        },
        (existingData, next) => {
          if (existingData.length === 0) {
            // All videos are new, skip to the next step
            return next(null, [], id);
          }
          // Remove existing data from ID array
          const obj = existingData.map(el => el._id);
          next(null, existingData, id.filter(el => !obj.includes(el)));
        },
        (existingData, newIDs, next) => {
          if (newIDs.length === 0) {
            return next(null, existingData);
          }
          // Get new videos' data from YT API
          youtube.videos.list({ id: newIDs.join(','), part: 'snippet,contentDetails,statistics' }, (err, videoResp) => {
            if (err) return next(err);
            // Final data
            const data = id;

            // New videos' data
            const newData = videoResp.data.items.map(item => this.fixVideoData(item));
            // Add new videos to the DB
            Video.insertMany(newData, (err) => {
              if (err) return next(err);
              // Merge new data with existing data
              const merged = existingData.concat(newData);
              // Fix order
              for (let i = 0; i < merged.length; i += 1) {
                const d = merged[i];
                data[data.indexOf(d._id)] = d;
              }
              // Success!
              next(null, data);
            });
          });
        },
      ], (err, data) => callback(err, data));
    }
  }

  static fixVideoData(videoData) {
    const data = {
      _id: videoData.id,
      channelId: videoData.snippet.channelId,
      title: videoData.snippet.title,
      description: videoData.snippet.description,
      slug: slugify(videoData.snippet.title, { lower: true }),
      views: videoData.statistics.viewCount,
      duration: moment.duration(videoData.contentDetails.duration).asSeconds(),
      tags: videoData.snippet.tags,
      thumbnail: null,
      preThumbnail: null,
      time: videoData.snippet.publishedAt,
    };

    const possibleThumbs = ['maxres', 'standard', 'high', 'medium', 'default'];
    for (let j = 0; j < possibleThumbs.length; j += 1) {
      if (Object.prototype.hasOwnProperty.call(videoData.snippet.thumbnails, possibleThumbs[j])) {
        data.thumbnail = videoData.snippet.thumbnails[possibleThumbs[j]].url;
        break;
      }
    }

    if (videoData.snippet.thumbnails.medium) {
      data.preThumbnail = videoData.snippet.thumbnails.medium.url;
    } else if (videoData.snippet.thumbnails.high) {
      data.preThumbnail = videoData.snippet.thumbnails.high.url;
    } else {
      data.preThumbnail = data.thumbnail;
    }

    return data;
  }

这是videos数组包含的内容:

// videoData: https://developers.google.com/youtube/v3/docs/videos#resource
{
    _id: videoData.id,
    channelId: videoData.snippet.channelId,
    title: videoData.snippet.title,
    description: videoData.snippet.description,
    views: videoData.statistics.viewCount,
    duration: moment.duration(videoData.contentDetails.duration).asSeconds(),
    tags: videoData.snippet.tags,
    thumbnail: null,
    preThumbnail: null,
    time: videoData.snippet.publishedAt,
};

预期结果:

[...{ [..other keys] duration: "00:05:43", time: "3 days ago" }]

实际输出(不做任何更改,与videos完全相同的数组):

[...{ [..other keys] duration: 343, time: 2018-12-26T13:37:32.000Z }]

为什么它不起作用,我该如何解决?

2 个答案:

答案 0 :(得分:0)

您可以返回一个新对象,在其中您仅覆盖这两个特定键,

video.map(v => ({ 
    ...v, 
    duration: moment('1900-01-01 00:00:00').seconds(v.duration).format('HH:mm:ss'),
    time: moment(v.time).fromNow()
}))

答案 1 :(得分:0)

因此,显然Model.find()返回猫鼬文档而不是javascript对象,我应该使用Query.lean()

Video.find({ _id: { $in: id } }).lean().select('-__v').sort({ createdAt: 1 })
        .exec()