为什么我的 for...of 循环返回空数组,Javascript 节点
Why is my for...of loop returning empty array, Javascript Node
我正在尝试通过 express/node 上传从前端 formData 发送到 Firebase 存储的三张 post 图片。我喜欢 return 对象数组的函数,每个对象都有图像名称和 publicUrl,然后我可以将其保存在 Firestore 中相应的 Post 文档中。
下面当前代码的问题在于它return是一个空数组[]。尽管 urls.push() 方法中的日志显示了正确的数组,但我只是不知道如何从以下 .then() 方法访问它。
感谢您的帮助!
router.post(
"/",
auth,
uploader.fields([
{ name: "cardImage", maxCount: 1 },
{ name: "postImageOne", maxCount: 1 },
{ name: "postImageTwo", maxCount: 1 },
]),
async (req, res, next) => {
try {
const { title, caption, content } = req.body;
const { uid } = req.user;
//add images to storage
const imagesWriteFunction = async () => {
var urls = [];
for (const [key, value] of Object.entries(req.files)) {
console.log(`---Starting upload process for ${key}---`);
const blob = bucket.file(`${value[0].originalname}`);
const blobWriter = blob.createWriteStream({
metadata: {
contentType: value[0].mimetype,
},
});
blobWriter.on("error", (err) => next(err));
blobWriter.on("finish", () => {
console.log("---Assemblying Public URL---", blob.name);
const publicUrl = `https://firebasestorage.googleapis.com/v0/b/${
bucket.name
}/ImagePosts/o/${encodeURI(blob.name)}?alt=media`;
urls.push(`{ ${key}: ${publicUrl} }`);
console.log("urls push log", urls);
});
console.log("urls .on() log", urls);
blobWriter.write(value[0].buffer);
blobWriter.end();
}
return urls;
};
imagesWriteFunction().then( (urls) => {
console.log("iamgeUrls log", urls);
//I a want to access urls here so I can send with other form data to Post doc in firestore.
});
res.status(200).send(newPostData);
} catch (err) {
console.log("createPost error", err);
}
}
);
console.log
---Starting upload process for cardImage---
Sending image cardImage: [object Object] to Storage
---Starting upload process for postImageOne---
Sending image postImageOne: [object Object] to Storage
---Starting upload process for postImageTwo---
Sending image postImageTwo: [object Object] to Storage
urls log []
imagesWriteFunction urls log []
---newPostRes--- zt0OkMbLg2osceAtf3Vo
---Successfully added to user posts array--- WriteResult {
_writeTime: Timestamp { _seconds: 1622789685, _nanoseconds: 86941000 }
}
---Assemblying Public URL--- woodywoodpecker.png
urls push log [
'{ postImageOne: https://firebasestorage.googleapis.com/v0/b/devport-express-backend.appspot.com/ImagePosts/o/woodywoodpecker.png?alt=media }'
]
---Assemblying Public URL--- images.jpg
urls push log [
'{ postImageOne: https://firebasestorage.googleapis.com/v0/b/devport-express-backend.appspot.com/ImagePosts/o/woodywoodpecker.png?alt=media }',
'{ postImageTwo: https://firebasestorage.googleapis.com/v0/b/devport-express-backend.appspot.com/ImagePosts/o/images.jpg?alt=media }'
]
---Assemblying Public URL--- johnnybravo.jpg
urls push log [
'{ postImageOne: https://firebasestorage.googleapis.com/v0/b/devport-express-backend.appspot.com/ImagePosts/o/woodywoodpecker.png?alt=media }',
'{ postImageTwo: https://firebasestorage.googleapis.com/v0/b/devport-express-backend.appspot.com/ImagePosts/o/images.jpg?alt=media }',
'{ cardImage: https://firebasestorage.googleapis.com/v0/b/devport-express-backend.appspot.com/ImagePosts/o/johnnybravo.jpg?alt=media }'
]
[nodemon] restarting due to changes...
[nodemon] starting `node index index.js`
Server started on port: 5000
您的 for ... of 循环没有返回任何内容,因为 blobWriter 在填充您的 urls 数组之前正在等待事件“完成”,因此您在操作完成之前离开该函数,最后什么也得不到。正如您在日志中清楚地看到的那样,首先您得到了 urls log [] imagesWriteFunction urls log []
,然后当事件“完成”被触发时,您得到了 blobWrite 的实际结果。
为防止这种正常行为,您可以使用 Promise 来“承诺”此调用并能够等待它,这里是一种方法 (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise):
const blobWriterAsync = (value, key) =>
new Promise((resolve, reject) => {
const blob = bucket.file(`${value[0].originalname}`);
const blobWriter = blob.createWriteStream({
metadata: {
contentType: value[0].mimetype
}
});
blobWriter.on('error', (err) => reject(err)); // <==== REJECT so you can catch the error later
blobWriter.on('finish', () => {
console.log('---Assemblying Public URL---', blob.name);
const publicUrl = `https://firebasestorage.googleapis.com/v0/b/${bucket.name}/ImagePosts/o/${encodeURI(blob.name)}?alt=media`;
resolve(`{ ${key}: ${publicUrl} }`) // <== RESOLVE so you can await for it or use .then
});
blobWriter.write(value[0].buffer);
blobWriter.end();
});
const imagesWriteFunction = async () => {
var urls = [];
for (const [key, value] of Object.entries(req.files)) {
try {
const url = await blobWriterAsync(value, key)
urls.push(url);
} catch (err) {
console.log("do something with err");
}
}
return urls;
};
我正在尝试通过 express/node 上传从前端 formData 发送到 Firebase 存储的三张 post 图片。我喜欢 return 对象数组的函数,每个对象都有图像名称和 publicUrl,然后我可以将其保存在 Firestore 中相应的 Post 文档中。
下面当前代码的问题在于它return是一个空数组[]。尽管 urls.push() 方法中的日志显示了正确的数组,但我只是不知道如何从以下 .then() 方法访问它。
感谢您的帮助!
router.post(
"/",
auth,
uploader.fields([
{ name: "cardImage", maxCount: 1 },
{ name: "postImageOne", maxCount: 1 },
{ name: "postImageTwo", maxCount: 1 },
]),
async (req, res, next) => {
try {
const { title, caption, content } = req.body;
const { uid } = req.user;
//add images to storage
const imagesWriteFunction = async () => {
var urls = [];
for (const [key, value] of Object.entries(req.files)) {
console.log(`---Starting upload process for ${key}---`);
const blob = bucket.file(`${value[0].originalname}`);
const blobWriter = blob.createWriteStream({
metadata: {
contentType: value[0].mimetype,
},
});
blobWriter.on("error", (err) => next(err));
blobWriter.on("finish", () => {
console.log("---Assemblying Public URL---", blob.name);
const publicUrl = `https://firebasestorage.googleapis.com/v0/b/${
bucket.name
}/ImagePosts/o/${encodeURI(blob.name)}?alt=media`;
urls.push(`{ ${key}: ${publicUrl} }`);
console.log("urls push log", urls);
});
console.log("urls .on() log", urls);
blobWriter.write(value[0].buffer);
blobWriter.end();
}
return urls;
};
imagesWriteFunction().then( (urls) => {
console.log("iamgeUrls log", urls);
//I a want to access urls here so I can send with other form data to Post doc in firestore.
});
res.status(200).send(newPostData);
} catch (err) {
console.log("createPost error", err);
}
}
);
console.log
---Starting upload process for cardImage---
Sending image cardImage: [object Object] to Storage
---Starting upload process for postImageOne---
Sending image postImageOne: [object Object] to Storage
---Starting upload process for postImageTwo---
Sending image postImageTwo: [object Object] to Storage
urls log []
imagesWriteFunction urls log []
---newPostRes--- zt0OkMbLg2osceAtf3Vo
---Successfully added to user posts array--- WriteResult {
_writeTime: Timestamp { _seconds: 1622789685, _nanoseconds: 86941000 }
}
---Assemblying Public URL--- woodywoodpecker.png
urls push log [
'{ postImageOne: https://firebasestorage.googleapis.com/v0/b/devport-express-backend.appspot.com/ImagePosts/o/woodywoodpecker.png?alt=media }'
]
---Assemblying Public URL--- images.jpg
urls push log [
'{ postImageOne: https://firebasestorage.googleapis.com/v0/b/devport-express-backend.appspot.com/ImagePosts/o/woodywoodpecker.png?alt=media }',
'{ postImageTwo: https://firebasestorage.googleapis.com/v0/b/devport-express-backend.appspot.com/ImagePosts/o/images.jpg?alt=media }'
]
---Assemblying Public URL--- johnnybravo.jpg
urls push log [
'{ postImageOne: https://firebasestorage.googleapis.com/v0/b/devport-express-backend.appspot.com/ImagePosts/o/woodywoodpecker.png?alt=media }',
'{ postImageTwo: https://firebasestorage.googleapis.com/v0/b/devport-express-backend.appspot.com/ImagePosts/o/images.jpg?alt=media }',
'{ cardImage: https://firebasestorage.googleapis.com/v0/b/devport-express-backend.appspot.com/ImagePosts/o/johnnybravo.jpg?alt=media }'
]
[nodemon] restarting due to changes...
[nodemon] starting `node index index.js`
Server started on port: 5000
您的 for ... of 循环没有返回任何内容,因为 blobWriter 在填充您的 urls 数组之前正在等待事件“完成”,因此您在操作完成之前离开该函数,最后什么也得不到。正如您在日志中清楚地看到的那样,首先您得到了 urls log [] imagesWriteFunction urls log []
,然后当事件“完成”被触发时,您得到了 blobWrite 的实际结果。
为防止这种正常行为,您可以使用 Promise 来“承诺”此调用并能够等待它,这里是一种方法 (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise):
const blobWriterAsync = (value, key) =>
new Promise((resolve, reject) => {
const blob = bucket.file(`${value[0].originalname}`);
const blobWriter = blob.createWriteStream({
metadata: {
contentType: value[0].mimetype
}
});
blobWriter.on('error', (err) => reject(err)); // <==== REJECT so you can catch the error later
blobWriter.on('finish', () => {
console.log('---Assemblying Public URL---', blob.name);
const publicUrl = `https://firebasestorage.googleapis.com/v0/b/${bucket.name}/ImagePosts/o/${encodeURI(blob.name)}?alt=media`;
resolve(`{ ${key}: ${publicUrl} }`) // <== RESOLVE so you can await for it or use .then
});
blobWriter.write(value[0].buffer);
blobWriter.end();
});
const imagesWriteFunction = async () => {
var urls = [];
for (const [key, value] of Object.entries(req.files)) {
try {
const url = await blobWriterAsync(value, key)
urls.push(url);
} catch (err) {
console.log("do something with err");
}
}
return urls;
};