#node.js #express
Вопрос:
У меня есть 2 конечные точки: файл записи и файл удаления. writeToFile просто записывает фиктивный json. removeFromFile пытается удалить это фиктивное поле json, ранее записанное с помощью writeToFile.
На стороне клиента пользователь может вызвать файл removeFromFile только после того, как он вызвал конечную точку файла записи. Поскольку запись файла занимает 8 секунд, пользователь может нажать кнопку, которая запускает вызов api для удаления файла из файла до того, как этот json будет записан. Поэтому removeFromFile необходимо подождать, пока не будет записан фиктивный json, прежде чем пытаться удалить поле.
Я достигаю этого, используя setTimeout с жестко заданным временем. Однако как я могу это сделать, используя обещания или обратные вызовы?
Это мой код:
"use strict";
const fs = require("fs")
const path = require("path")
const express = require("express")
const server = express();
class FileController {
static async removeFromFile(req, res, next) {
setTimeout(async () => {
// read from file and remove from file and if success
return res.status(200).json({
success: true
});
}, 20000)
}
static async writeToFile(req, res, next) {
try {
const fileId = await new Promise(resolve=>setTimeout(()=>resolve("1234"),8000));
fs.writeFileSync(path.join(__dirname, "./config/fileIds.json"), JSON.stringify({foo: fileId}));
} catch (err) {
console.log(err);
return next(
new Error("Something went wrong when writing to file ...")
);
}
return res.status(200).json({
success: true,
});
}
}
server.get("/writeToFile", FileController.writeToFile)
server.get("/removeFromFile", FileController.removeFromFile)
const port = 8083;
server.listen(port,()=>{
console.log("Server running on port ", port)
})
Ответ №1:
Я нашел два разных решения. Один использует излучатели событий, а другой-setInterval.
- В решении «События» я установил тайм-аут для отправки ответа пользователю через 20 секунд на случай, если он не будет вызван эмитентом. Я также использую событие внутри res.on(«готово»…) из файла записи, чтобы не использовать его в файле удаления, потому что основная цель файла удаления-удалить файл до завершения записи.
- В решении setInterval я использую логическое значение после его записи, а затем setInterval для проверки состояния до тех пор, пока оно не будет обновлено. maxTimer настроен на остановку setInterval и выдачу ответа пользователю через 20 секунд.
решение для событий:
"use strict";
const fs = require("fs")
const path = require("path")
const express = require("express");
const EventEmitter = require("events");
const server = express();
const event = new EventEmitter();
const timers = [];
class FileController {
static async removeFromFile(req, res, next) {
const filePath = req.body.filePath;
const timer = setTimeout(() => {
event.emit("isWritten", true);
return res.status(400).json({
success: false
});
}, 20000)
timers.push(timer);
event.once("isWritten", (exit) => {
while (timers.length > 0) {
const time = timers.pop();
clearTimeout(time);
}
if (exit) return;
// read from file and remove from file and if success
return res.status(200).json({
success: true
});
})
}
static async writeToFile(req, res, next) {
const filePath = req.body.filePath;
const fileId = req.body.fileId;
const waitTime = req.body.waitTime;
try {
await new Promise(resolve => setTimeout(() => resolve(), waitTime));
const json = JSON.parse(fs.readFileSync(path.join(__dirname, "./config/fileIds.json")).toString());
json[filePath] = fileId;
fs.writeFileSync(path.join(__dirname, "./config/fileIds.json"), JSON.stringify(json));
event.emit("isWritten", false);
res.on("finish", async () => {
event.once("isWritten", () => {})
// read from file and remove from file
})
} catch (err) {
console.log(err);
return next(
new Error("Something went wrong when writing to file ...")
);
}
return res.status(200).json({
success: true,
});
}
}
server.get("/writeToFile", FileController.writeToFile)
server.get("/removeFromFile", FileController.removeFromFile)
const port = 8083;
server.listen(port, () => {
console.log("Server running on port ", port)
})
Сетинтервальное решение:
"use strict";
const fs = require("fs")
const path = require("path")
const express = require("express")
const server = express();
class FileController {
static isWritten = false;
static async removeFromFile(req, res, next) {
let maxTimer = 20;
let timer = 1;
const interval = setInterval(()=>{
timer = 1;
if(timer === maxTimer){
clearInterval(interval);
return res.status(400).json({
success: false
});
}
if(FileController.isWritten){
clearInterval(interval);
// read from file and remove from file and if success
return res.status(200).json({
success: true
});
}
},1000);
}
static async writeToFile(req, res, next) {
FileController.isWritten = false;
try {
const fileId = await new Promise(resolve=>setTimeout(()=>resolve("1234"),8000));
fs.writeFileSync(path.join(__dirname, "./config/fileIds.json"), JSON.stringify({foo: fileId}));
FileController.isWritten = true;
res.on("finish", async () => {
// read from file and remove from file
})
} catch (err) {
console.log(err);
return next(
new Error("Something went wrong when writing to file ...")
);
}
return res.status(200).json({
success: true,
});
}
}
server.get("/writeToFile", FileController.writeToFile)
server.get("/removeFromFile", FileController.removeFromFile)
const port = 8083;
server.listen(port,()=>{
console.log("Server running on port ", port)
})