在promise中使用Array.push时,Array保持为空

时间:2019-03-07 03:25:35

标签: arrays typescript firebase promise google-cloud-functions

我正在尝试从特定文件中收集所有文档,并将它们转换为具有content和filename属性的Sendgrid附件对象。

第1步和第2步正在运行。在执行完第2步之后,我将得到一个对象数组,其中包含一些文档数据,例如文件名,类型,存储URL等。

在步骤3中,我想基于存储URL提取实际文件并创建一个Sendgrid附件对象。它需要contentfilename作为属性。

但是,在我当前的代码中,当我记录变量时,attachments数组保持为空。

我的代码:

export const onStatusChanged = functions.database.ref(`files/{fileID}/general/status`).onUpdate(async (change, context) => {
    const prevStatus = change.before.val();
    const currentStatus = change.after.val();

    if (prevStatus === currentStatus) return null;

    if (currentStatus === 'email') {
        // 1. Get file data
        const snapshot = await change.after.ref.parent.parent.once('value');
        const file = snapshot.val();

        // 2. Get documents
        const documents = getDocuments(file.documents);
        console.log(documents);

        // 3. Create attachments
        const attachments = [];

        documents.forEach(document => {
            axios.get(document.url, { responseType: 'arraybuffer' }).then(image => {
                attachments.push({ content: Buffer.from(image.data).toString('base64'), filename: document.name });
            }).catch(error => {
                console.log(error)
            })
        });

        console.log(attachments) // []

        // 4. Create email object

        // 5. Send email
    }

    return null;
})

我以为通过使用我的诺言我的代码是同步的?

编辑:首先我有这段代码

    // 3. Create attachments
    const attachments = documents.map(document => {
        const image = await axios.get(document.url, { responseType: 'arraybuffer' });
        return attachments.push({ content: Buffer.from(image.data).toString('base64'), filename: document.name });
    })

    console.log(attachments) // [ Promise { <pending> } ]

2 个答案:

答案 0 :(得分:1)

我认为您误解了诺言在Cloud Functions中的使用。使用Cloud Functions后台触发器,您必须返回一个承诺,该承诺将在所有异步工作完全完成时解决,否则该工作将被关闭。现在,您返回的是null,这是不正确的。

此外,attachements似乎没有积累承诺。它会累积其他对异步编程无用的对象。

在文档中了解更多信息:https://firebase.google.com/docs/functions/terminate-functions

答案 1 :(得分:0)

将代码更改回异步/等待并添加了Promise.all()。就像我现在想要的那样工作。

代码:

    const attachments = await Promise.all(documents.map(async document => {
        const image = await axios.get(document.url, { responseType: 'arraybuffer' });
        return { content: Buffer.from(image.data).toString('base64'), filename: document.name };
    }));