Как я могу сделать свой второй блок в триггере цепи? - PullRequest
0 голосов
/ 04 июня 2019

У меня есть код для загрузки группы фотографий на сервер.

Весь код можно разделить на три части:

  • перехватывать картинки из input = "files" и помещать их в проверяемые файлы, пока я не вызову метод uploadPictures().

  • затем я загружаю фотографии и помещаю URL-адреса в массив, чтобы я мог использовать их позже

  • и, наконец, когда загрузка закончена, и у меня естьПо ссылке я хочу обновить определенный документ в БД (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 });

    })


  }


Буду признателен за любые советы или подсказки!

1 Ответ

1 голос
/ 04 июня 2019

Итак, я вижу здесь несколько вопросов о том, как вы выполняете обещания. Легко ошибиться, если вы новичок в этом, так что не расстраивайтесь.

Итак, первая проблема - как вы звоните new Promise. Этот конструктор принимает функцию с двумя параметрами: resolve и reject. Это функции, которые при вызове либо завершают, либо отклоняют обещание. Вы не делаете ни одного, поэтому первое обещание никогда не выполнится.

Вторая проблема, с которой вы столкнулись, заключается в том, что у вас есть вызовы по обещаниям внутри вызовов по обещаниям, но вы никогда не возвращаете обещания обратно в цепочку вызовов, поэтому вещи не объединяются должным образом.

В вашем случае, я не думаю, что new Promise() это правильная конструкция в любом случае. Я думаю, вам нужно просто раздать обещание, которое завершается, когда все обещания, которые вы вызываете внутри цикла, завершаются. Поэтому вам нужно создать массив всех обещаний внутри цикла, а затем вызвать для них Promise.all, чтобы получить новое обещание, которое завершается, когда все обещания в массиве выполнены.

Кроме того, весь этот процесс был бы намного проще, если бы вы просто везде использовали async / await вместо явного использования обещаний и вызовов 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 });
}

Надеюсь, это поможет!

...