文件上传异步功能不等待

时间:2020-05-05 09:55:35

标签: javascript firebase asynchronous async-await

我正在尝试创建一个用于批量处理文件上传的函数。我有一个所谓的楼层,每个楼层都有房间。每个房间都可以有一个音频文件。此功能应处理这些文件的上载。我的问题是在文件上传之前就写入了更新的“ floor”。这意味着我无法使其异步正常工作。

这是我的职能: -轨道是一个对象,其键是房间的索引,文件的值是文件本身(使用对象而不是数组,因为这是一个更新功能,因此我可能没有在该对象中拥有所有房间)。

export const saveFloor = (floor, tracks, cb) => async () => {
  const newFloor = { ...floor };

  if (tracks) {
    await Object.keys(tracks).forEach(async (trackKey) => {
      const track = tracks[trackKey];

      const ref = storage.ref(
        `/audio/floor_tracks/${floor.id}/${trackKey}/${track.name}`
      );

      const upload = await ref.put(track);
      if (!upload) return;

      const downloadUrl = await ref.getDownloadURL();
      if (!downloadUrl) return;

      newFloor.rooms[trackKey].track = { name: track.name, file: downloadUrl };
      console.log("this is the floor", "Just finished one track");
    });
    console.log("this is the floor", "Just finished all tracks");
  }
  console.log("this is the floor", newFloor.rooms);

  db.collection("floors")
    .doc(floor.id)
    .set(newFloor)
    .then(() => {
      cb();
    })
    .catch((e) => {
      console.log("Saving to db failed", e);
    });
};

我在Just finished all tracks之前打印了newFloor.roomsJust finished one track

RikkusRukkus的答案之后进行编辑,这是我当前的功能,但出现错误

Unhandled Rejection (TypeError): undefined is not iterable (cannot read property Symbol(Symbol.iterator))

export const saveFloor = (floor, logoFile, tracks, cb) => async () => {
  const newFloor = { ...floor };

  if (logoFile) {
    const ref = storage.ref(`/images/floor_logos/${floor.id}`);

    const upload = await ref.put(logoFile);
    if (!upload) return;

    const downloadUrl = await ref.getDownloadURL();
    if (!downloadUrl) return;

    newFloor.logo = downloadUrl;
  }

  if (tracks) {
    await Promise.all(
      Object.keys(tracks).forEach(async (trackKey) => {
        const track = tracks[trackKey];

        const ref = storage.ref(
          `/audio/floor_tracks/${floor.id}/${trackKey}/${track.name}`
        );

        const upload = await ref.put(track);
        if (!upload) return;

        const downloadUrl = await ref.getDownloadURL();
        if (!downloadUrl) return;

        newFloor.rooms[trackKey].track = {
          name: track.name,
          file: downloadUrl,
        };
        console.log("this is the floor", "Just finsihed one track");
      })
    );

    console.log("this is the floor", "Just finsihed all tracks");
  }
  console.log("this is the floor", newFloor.rooms);

  db.collection("floors")
    .doc(floor.id)
    .set(newFloor)
    .then(() => {
      cb();
    })
    .catch((e) => {
      console.log("Saving to db failed", e);
    });
};

1 个答案:

答案 0 :(得分:0)

await Object.keys(tracks).forEach(async (trackKey) => {

Array.prototype.forEach返回undefined,这不会引发错误,因为您可以await任意类型的值,而不仅仅是Promises。那么发生的是:

  1. 您的数组被循环
  2. 启动异步过程
  3. undefinedforEach返回
  4. 这不是一个承诺,因此它会立即解决,几乎没有延迟,下一行将被执行(“完成所有曲目”)
  5. 一段时间后,#2的承诺得以解决。解析的值什么也做不了(return语句中没有值,因此Promise将解析为undefined)。

您可以像这样等待一系列的诺言:

await Promise.all( Object.keys(tracks).map(async (trackKey) => { ... }) )

Array.prototype.map确实返回值,在这种情况下为Promises。 Promise.all接受一组Promises&solves,当所有解决方案都被拒绝或拒绝(“抛出”)时,任何人拒绝。

_

如果要在异步函数中包含return个值,那么Promise.all将按顺序解析为这些返回值的数组。