В части 5 блога мы рассмотрели, как передавать информацию между файлами, сохранять их и вызывать их обратно, используя формат JSON. Пришло время применить то, что мы узнали, к нашему приложению для создания заметок в этом блоге.
Мы собираемся работать с созданным файлом «note.js». Внутри этого файла создадим первую функцию:
const getNotes = function () {
return 'saved notes'
}
module.exports = {
getNotes
}
На данный момент эта функция не возвращает ничего, кроме строки, но мы скоро это исправим. Затем мы экспортируем функцию, чтобы иметь возможность использовать ее в других файлах, экспортируемые данные на этот раз являются объектом, что позволит нам экспортировать несколько функций, если имя свойства и значение совпадают, мы можем написать после того, как имя функции, иначе нам нужно указать имя свойства, если оно отличается. Например, если имя свойства отличается, мы напишем:
module.exports = {
addFunction: getNotes
}
Вместо этого, если то же самое, мы не пишем:
module.exports = {
getNotes: getNotes
}
мы можем это не ошибка, но лучше упростить, написав только один раз название:
module.exports = {
getNotes
}
Вторая функция будет функцией, отвечающей за добавление заметки, в нашу «getNotes», которую мы добавляем:
const addNote = function (title, body) {
console.log(title, body)
}
Эта функция принимает в качестве аргументов заголовок и тело заметки. На данный момент мы ничего не делаем, кроме как записываем в консоль значение, чтобы проверить, работает ли оно.
Теперь в наш файл «app.js» нам нужно импортировать файлы:
const {getNotes, addNote} = require(‘./notes’)
Здесь мы применяем назначение реструктуризации, чтобы получить доступ к значению в объекте, который мы возвращаем.
Мы собираемся использовать нашу функцию «addNote()» в созданной нами команде добавления.
yargs.command({
command :"add",
describe: "add a note",
builder:{
title: {
describe: 'Note title',
demandOption: true,
type: 'string'
},
body:{
describe: "Note body",
demandOption: true,
type: 'string'
}
},
handler: function (argv) {
addNote(argv.title, argv.body)
},
})
Внутри нашей функции-обработчика мы вызываем «addNote()» и получаем доступ к нашему объекту «argv», который хранит заголовок и тело нашей заметки и передает их в качестве аргумента. Мы можем протестировать нашу функцию, добавив заметку в консоль, как и раньше, и посмотреть, будет ли она напечатана из нашей функции;
node app.js add --title="test Title" --body="test body"
Если заголовок и тело, которое вы передали, напечатались в консоли, значит, наша функция пока работает отлично.
Теперь пришло время создать наш файл JSON и сохранить данные заметок внутри. В нашем файле «note.js» мы создаем функцию для загрузки информации в файл «note.json», в котором будет храниться вся заметка.
const loadNotes = function () {
try {
const dataBuffer = fs.readFileSync("notes.json");
const dataJSON = dataBuffer.toString();
return JSON.parse(dataJSON);
} catch (e) {
return [];
}
};
В этой функции мы создали оператор «попробуй и поймай», потому что, если мы сначала попытаемся загрузить файл из несуществующего файла, это означает, что мы вызываем эту функцию в первый раз, и мы еще не выполнили наши действия. Файл «notes.json» выдаст ошибку. Чтобы предотвратить это, мы сначала запустим оператор «try», а в случае ошибки запустим оператор «cath», который вернет пустой массив. Эта функция будет вызываться внутри нашей функции «addNote».
const addNote = function (title, body) {
const notes = loadNotes();
}
Здесь мы присваиваем переменной notes либо сохраненные ранее заметки, либо пустой массив, если это первая добавляемая заметка. Далее нам нужно сохранить внутри этого массива новый объект, содержащий заголовок и тело нашей заметки.
const addNote = function (title, body) {
const notes = loadNotes();
notes.push({
title,
body,
});
}
Мы используем метод push, чтобы добавить этот новый объект в массив, и, поскольку свойства и значение имеют то же имя, что и раньше, мы можем сократить синтаксис, вызывая оба только один раз с одним и тем же именем в объекте.
Если вы заметили до сих пор, у нас нет возможности сохранить наши заметки, и это то, что мы собираемся сделать дальше. Поскольку мы, вероятно, собираемся использовать эту функцию в нескольких местах, лучше сделать отдельную функцию справки, которую мы можем вызывать в любое время, когда нам нужно.
const saveNotes = function (notes) {
const dataJSON = JSON.stringify(notes);
fs.writeFileSync("notes.json", dataJSON);
};
Эта функция берет массив заметок, который мы создали ранее, сохраняет внутри новые заметки и преобразует данные в формат JSON, как мы видели в части 4 нашего блога. Затем он вызывает метод «fs» и создает файл «notes.json» и сохраняет данные JSON внутри или, если файл существует, добавляет новые данные в этот файл.
Мы вызываем эту функцию в конце функции «addNote»:
const addNote = function (title, body) {
const notes = loadNotes();
notes.push({
title,
body,
} );
saveNotes(notes);
};
Если мы сейчас вызовем команду add в нашей консоли и добавим новые заметки, она должна создать новый файл и сохранить в формате JSON наши заметки;
node app.js — title= “MY TITLE” — body= “MY BODY”
Вот что мы должны получить в новом созданном файле:
[{"title":"MY TITLE","body":"MY BODY"}]
Ух ты!! До сих пор мы могли позволить пользователю вводить заметки в консоли и сохранять их в новый файл. Но что произойдет, если пользователь дважды введет одно и то же значение или попытается продублировать нашу заметку? Нам нужно добавить сюда некоторую условную логику, чтобы этого не произошло.
во-первых, нам нужно проверить, существует ли уже заголовок или отметить, и мы собираемся создать новую переменную, которая хранит внутри все дублированные заголовки:
const existingNotes = notes.filter((note) =>{
return note.title === title
})
Теперь нам нужно проверить, имеет ли эта новая переменная нулевую длину или нет, если длина равна нулю, это означает, что мы не нашли дубликатов для добавления. Мы можем продолжить нашу функцию и сохранить новые заметки, но нам не нужно сообщать пользователю, что этот заголовок уже занят, и останавливать функцию:
if(existingNotes === 0) {
notes.push({
title,
body,
});
saveNotes(notes);
} else {
console.log('Note title already exists')
}
Теперь вы можете протестировать эту функцию и посмотреть, работает ли она, она должна добавить заметку, если заголовок не существует, в противном случае должно утешать сообщение для пользователя о том, что этот заголовок заметки уже существует.
В этом блоге мы реализовали команду добавления и увидели, как можно создать файл и сохранить информацию из пользовательской команды. В следующем блоге продолжаем реализовывать функцию и убираем функционал.