【问题标题】:How can I make my second block in the chain trigger?我怎样才能使我的第二块链触发?
【发布时间】:2019-06-03 23:12:40
【问题描述】:

我有一些用于将一堆照片上传到服务器的代码。

整个代码可以分为三部分:

  • 从 input="files" 捕获图片并将它们放在一个可验证的文件中,直到我调用方法 uploadPictures()。

  • 然后我正在上传照片并将网址推送到数组中,以便我以后可以使用它们

  • 最后,当上传结束时,我有了想要更新数据库(Firestore)中某个文档的链接

问题在于前两部分的代码运行良好。我可以让这个链既不使用 async/await 也不使用 Promises


async uploadPictures() {

    let loop = new Promise( result => {

      this.files.forEach((file, index) => {

        let path: string = `items/${Date.now()}_${this.files[index].name}`;

        let ref = this.storage.ref(path);

        ref.put(file).then(snapshot => {
          snapshot.ref.getDownloadURL().then(downloadLink => {
            this.url.push(downloadLink);
            console.log('Image is uploaded successfully and available at: ' + downloadLink);
          })
        });
      });

    }).then( () => {

      console.log('hello from here!');
      console.log(this.url);
      this.firestore.collection('items').doc(this.itemId).update({ pics: this.url });

    })


  }


我将不胜感激任何提示或建议!

【问题讨论】:

  • 您能再解释一下吗?我很难弄清楚“第二个承诺”是什么。你能否更明确地说出你期望得到什么以及你实际得到什么?我想我至少发现了一个问题,但我不确定这是否是您真正想要解决的问题。
  • promise 构造函数永远不会解析
  • @ChrisTavares 已更新
  • @PatrickRoberts 你能给我解释一下吗,因为你可以看到我不擅长承诺)

标签: angular typescript es6-promise chaining


【解决方案1】:

所以我在这里看到了你如何做承诺的多个问题。如果您是新手,很容易弄错,所以不要为此感到难过。

所以第一个问题是您调用new Promise 的方式。此构造函数采用具有两个参数的函数:resolvereject。这些是在调用时完成或拒绝承诺的函数。你什么都不做,所以第一个承诺永远不会完成。

您遇到的第二个问题是您在 Promise 调用中进行了 Promise 调用,但您永远不会将 Promise 返回到调用链中,因此事情不会正确地链接在一起。

在您的情况下,我认为new Promise() 无论如何都不是正确的构造。我认为你需要简单地传递一个当你在循环内调用的所有承诺完成时完成的承诺。所以你需要做的是在循环中构造一个包含所有 Promise 的数组,然后在它们上调用 Promise.all 以获得一个新的 Promise,当数组中的所有 Promise 都完成时,它就会完成。

此外,如果您只是在任何地方都使用 async/await 而不是显式使用 Promise 和 then 调用,那么整个过程会容易得多。 :-)

我认为使用显式承诺您想要做的事情看起来像这样:

// Don't need async if not awaiting
uploadPictures() {
    // Build array of promises for each item in loop.
    // Array.map is an easy way to do this.
    let loop = this.files.map((file, index) => {
        let path: string = `items/${Date.now()}_${this.files[index].name}`;
        let ref = this.storage.ref(path);

        // Inner promise - MUST RETURN THIS to chain properly
        // Also, prefer flattened promise chains to nested one
        return ref.put(file)
        .then(snapshot => snapshot.ref.getDownloadURL())
        .then(downloadLink => {
            this.url.push(downloadLink);
            console.log('Image is uploaded successfully and available at: ' + downloadLink);
        });
    });
    return Promise.all(loop)
    .then(() => {
        console.log('hello from here!');
        console.log(this.url);
        return this.firestore.collection('items').doc(this.itemId).update({ pics: this.url });
    });
}

当使用async/await 时,这会变得更干净:

async uploadPictures() {
    // Build array of promises for each item in loop.
    // Array.map is an easy way to do this.
    let loop = this.files.map(async (file, index) => {
        let path: string = `items/${Date.now()}_${this.files[index].name}`;
        let ref = this.storage.ref(path);

        // await lets us avoid explicit returns or chaining
        let snapshot = await ref.put(file);
        let downloadUrl = await snapshot.ref.getDownloadURL();
        this.url.push(downloadLink);
        console.log('Image is uploaded successfully and available at: ' + downloadLink);
    });

    await Promise.all(loop);
    console.log('hello from here!');
    console.log(this.url);
    await this.firestore.collection('items').doc(this.itemId).update({ pics: this.url });
}

希望这会有所帮助!

【讨论】:

  • 非常感谢!带有承诺的版本对我有用,但带有 async/await 的版本抛出了同样的错误。
  • 如果这个答案有帮助,请记得点赞和/或接受答案。
  • 所有的链都应该返回吗?一个人说了一些关于构造函数的事情。你能给我解释一下吗?))
  • 回复。 async/await 版本,好吧,我只是即时输入,没有尝试过,所以没有关于正确性的承诺(呵呵!)。
  • 构造函数是我在答案顶部提到的 - 你错误地使用了 Promise 构造函数。至于返回,我的版本确实在每个 then 处理程序中返回,只是我使用的是 lambda 的表达式版本(注意 lambda 的主体周围没有大括号),这意味着返回是自动的,你不要'不需要明确的return 语句。但它确实返回了一个值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-26
  • 2013-08-14
  • 2013-06-29
  • 2011-01-02
  • 2010-10-18
相关资源
最近更新 更多