我怎样才能使链中的第二个块触发?

How can I make my second block in the chain trigger?

我有一些代码可以将一堆照片上传到服务器。

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

问题在于前两部分的代码运行良好。我可以让这条链既不使用 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 });

    })


  }


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

所以我在这里看到了关于您如何履行承诺的多个问题。如果您是新手,很容易犯这些错误,所以不要为此感到难过。

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

你遇到的第二个问题是你在 promise 调用中有 promise 调用,但你从来没有 return promise 备份调用链,所以事情没有正确地链接在一起。

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

此外,如果您只在所有地方使用 async/await 而不是显式使用 promises 和 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 });
}

希望对您有所帮助!