[CRUDμ μ΄μ©ν File upload Web] (9) user λ°μ΄ν° μμ νκΈ° & λκΈ°μ λΉλκΈ°
<λ³Έ λΈλ‘κ·Έλ DCodeMania μ μ νλΈλ₯Ό μ°Έκ³ ν΄μ 곡λΆνλ©° μμ±νμμ΅λ :-)>
=> CRUD App With Image Upload Using NodeJs, ExpressJs, MongoDB & EJS Templating Engine
π₯ λκΈ°(synchronous)
: μ§λ ¬μ μΌλ‘ νμ€ν¬λ₯Ό μν
: μμ²μ λ³΄λΈ ν μλ΅μ λ°μμΌμ§λ§ λ€μ λμμ΄ μ΄λ£¨μ΄μ§λ λ°©μ (νμ€ν¬λ₯Ό μ²λ¦¬ν λμ λλ¨Έμ§ νμ€ν¬λ λκΈ°)
π₯ λΉλκΈ° (asynchronous)
: λ³λ ¬μ μΌλ‘ νμ€ν¬λ₯Ό μν
: μμ²μ λ³΄λΈ ν μλ΅μ μλ½ μ¬λΆμλ μκ΄μμ΄ λ€μ νμ€ν¬κ° λμνλ λ°©μ (a νμ€ν¬κ° μ€νλλ μκ° λμ b νμ€ν¬ ν¨)
: λΉλκΈ° μμ²μ μλ΅ ν μ²λ¦¬ν 'μ½λ°± ν¨μ' μλ €μ€ => ν΄λΉ νμ€ν¬κ° μλ£λμμ λ, 'μ½λ°± ν¨μ'κ° νΈμΆλ¨
β νμ μ²λ¦¬ λ©μλ
1) Promise
then (Promise λ°ν)
: λ κ°μ μ½λ°± ν¨μλ₯Ό μΈμλ‘ μ λ¬ λ°μ
: 첫 λ²μ§Έ μ½λ°± ν¨μλ μ±κ³΅(fulfilled, resolve ν¨μκ° νΈμΆλ μν) μ νΈμΆλκ³
λ λ²μ§Έ ν¨μλ μ€ν¨(rejected, reject ν¨μκ° νΈμΆλ μν) μ νΈμΆ
: then λ©μλλ Promiseλ₯Ό λ°ν
// Promise κ°μ²΄μ μμ± const promise = new Promise((resolve, reject) => { // λΉλκΈ° μμ μ μννλ€. if (/* λΉλκΈ° μμ μν μ±κ³΅ */) { resolve('result'); } else { /* λΉλκΈ° μμ μν μ€ν¨ */ reject('failure reason'); } });
catch μμΈ
: λΉλκΈ° μ²λ¦¬μμ λ°μν μλ¬μ then λ©μλμμ λ°μν μλ¬κ° λ°μνλ©΄ νΈμΆ
: catch λ©μλλ Promiseλ₯Ό λ°ν
3) asyncμ await
async
: function μμ asyncλ₯Ό λΆμ΄λ©΄ ν΄λΉ ν¨μλ νμ νλΌλ―Έμ€λ₯Ό λ°ν
await
: async ν¨μ μμμλ§ λμ, νλΌλ―Έμ€κ° μ²λ¦¬λ λ κΉμ§ κΈ°λ€λ¦¬λ μν => κ²°κ³Όλ κ·Έ μ΄ν λ°ν
async function ν¨μλͺ () { await λΉλκΈ°_μ²λ¦¬_λ©μλ_λͺ (); }
π₯ user λ°μ΄ν° μμ νκΈ°
π§ routes/routes.js
const express = require("express");
const router = express.Router();
const User = require("../models/user");
const multer = require("multer");
const fs = require("fs");
// image upload
var storage = multer.diskStorage({
// νμΌμ΄ μ
λ‘λλ κ²½λ‘ μ€μ
destination: function (req, file, cb) {
cb(null, "./uploads");
},
// timestampλ₯Ό μ΄μ©ν΄ μλ‘μ΄ νμΌλͺ
μ€μ
filename: function (req, file, cb) {
cb(null, file.fieldname + "_" + Date.now() + "_" + file.originalname);
}
})
var upload = multer({
storage: storage,
}).single("image"); // ν κ°μ μ΄λ―Έμ§ μ²λ¦¬
// Insert an user into database route
router.post("/add", upload, (req, res) => {
const user = new User({
name: req.body.name,
email: req.body.email,
phone: req.body.phone,
image: req.file.filename,
});
user.save().then((err) => {
// index.js μ res.locals.message μμ
req.session.message = {
type: "success",
message: "User added successsfull!"
};
// μ§μ λ λ€λ₯Έ URLλ‘ μ¬μμ² (ν)
res.redirect("/");
}).catch((err) => {
res.json({ message: err.message, type: "danger" });
})
});
// 1) Get all users route
router.get("/", async (req, res) => {
const user = await User.find();
try {
// Queryλ₯Ό μ΄μ©ν λ νλ‘λ―Έμ€λ₯Ό 리ν΄λ°κ³ μΆλ€λ©΄ exec() λ©μλλ₯Ό μ΄μ©
// find()λ₯Ό μ€ννμ¬ Queryμ μΈμ€ν΄μ€λ₯Ό 리ν΄
res.render("index", {
title: "Home Page",
// κΆκΈ : λ μ error μ‘νλ?
users: user
});
} catch (error) {
(error) => {
res.json({ message: error.message });
}
};
});
router.get("/add", (req, res) => {
res.render("addUsers", { title: "Add users" });
})
// 2) Edit an user routes
router.get("/edit/:id", async (req, res) => {
let id = req.params.id;
const user = await User.findById(id);
try {
if (user == null) {
res.redirect("/");
} else {
res.render("editUsers", {
title: "Edit User",
user: user,
});
}
} catch (err) {
res.redirect("/");
}
});
// 3) Update user route
router.post("/update/:id", upload , async (req, res) => {
let id = req.params.id;
let new_image = "";
if (req.file) {
new_image = req.file.filename;
try {
// λκΈ° λ°©μμΌλ‘ νμΌ μ 보 μ½κΈ°
fs.readFileSync("./uploads/" + req.body.old_image);
} catch(err) {
console.log(err);
}
} else {
req.image = req.body.old_image;
}
// 첫 λ²μ§Έ μΈμλ μ
λ°μ΄νΈ νκ³ μ νλ λ¬Έμμ id, λ λ²μ§Έ μΈμλ μ
λ°μ΄νΈ ν μ 보 νΉμ λ΄μ©
const user = await User.findByIdAndUpdate(id, {
name : req.body.name,
email : req.body.email,
phone : req.body.phone,
image : new_image
});
try {
req.session.message = {
type : "success",
message :"User updated successfully!",
};
res.redirect("/");
} catch (err) {
res.json({ message : err.message, type : "danger"});
}
});
module.exports = router;
π§ views/editUsers.ejs
<%- include("layout/header") %>
<div class="container">
<div class="row">
<div class="col-lg-6 mx-auto mt-4">
<div class="card shadow">
<div class="card-header bg-success">
<h3 class="text-light">Edit User (<%= user.name %>)</h3>
</div>
<div class="card-body p-4">
<!-- addλ router κ²½λ‘ κ°μμΌ λ λ―? -->
<form action="/update/<%= user._id %>" method="post" id="add-form"
enctype="multipart/form-data">
<div class="mb-3">
<label for="name">Name</label>
<input type="text" name="name" class="form-control form-control-lg"
placeholder="Enter name" value="<%= user.name %>" required />
</div>
<div class="mb-3">
<label for="email">Email</label>
<input type="email" name="email" class="form-control form-control-lg"
placeholder="Enter email" value="<%= user.email %>" required />
</div>
<div class="mb-3">
<label for="phone">Phone</label>
<input type="tel" name="phone" class="form-control form-control-lg"
placeholder="Enter phone" value="<%= user.phone %>" required />
</div>
<div class="mb-3">
<label for="image" class="form-label">Select Image</label>
<input type="file" name="image" class="form-control form-control-lg" />
<img src="/<%= user.image %>" width="100" class="img-thumbnail mt-1">
</div>
<input type="hidden" name="old_image" value="<%= user.image %>">
<div class="mb-3 d-grid">
<input type="submit" name="submit" value="Update User" class="btn btn-success btn-lg" />
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<%- include("layout/footer") %>