Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 使用Array.push-in承诺时,数组保持为空_Arrays_Typescript_Firebase_Promise_Google Cloud Functions - Fatal编程技术网

Arrays 使用Array.push-in承诺时,数组保持为空

Arrays 使用Array.push-in承诺时,数组保持为空,arrays,typescript,firebase,promise,google-cloud-functions,Arrays,Typescript,Firebase,Promise,Google Cloud Functions,我试图从一个特定的文件中收集所有文档,并将它们转换为一个具有content和filename属性的Sendgrid附件对象 步骤1和2正在工作。在第2步之后,我有一个对象数组,其中包含一些文档数据,如文件名、类型、存储URL等 在步骤3中,我希望根据存储URL获取实际文件并创建Sendgrid附件对象。它需要内容和文件名作为属性 但是,在我当前的代码中,当我记录变量时,attachments数组保持为空 我的代码: export const onStatusChanged = functions

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

步骤1和2正在工作。在第2步之后,我有一个对象数组,其中包含一些文档数据,如文件名、类型、存储URL等

在步骤3中,我希望根据存储URL获取实际文件并创建Sendgrid附件对象。它需要
内容
文件名
作为属性

但是,在我当前的代码中,当我记录变量时,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> } ]
//3。创建附件
const attachments=documents.map(document=>{
const image=await axios.get(document.url,{responseType:'arraybuffer'});
返回attachments.push({content:Buffer.from(image.data).toString('base64'),filename:document.name});
})
console.log(附件)/[Promise{}]

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

而且,
附件
似乎并没有积累承诺。它正在积累对异步编程不有用的其他对象


阅读文档中的更多内容:

将代码改回async/await,并添加了
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 };
    }));

“我认为通过使用承诺,我的代码是同步的?”->正如您所发现的,事实并非如此。异步代码的顺序化有不同的方法——我们以前做过
async.failter
,也许现在仍然这样做。您可能正在考虑使用
wait
。这个新关键字使异步代码看起来是同步的,尽管它仍然是绝对异步的。您在
forEach
中尝试过
wait
吗?@RayToal:首先,我使用了带有
map()
函数的wait。添加此代码我将检查文档,然后返回。感谢您提供的url。将代码更改为async/await,并将循环包装在
Promise.all()
中。在if条件(步骤5)结束时,我将在发送实际电子邮件时返回承诺。