Зрозумійте виклики REST Backbone.js


77

Я намагаюся зрозуміти метод синхронізації Backbone.js і переглядав документацію на http://backbonejs.org/#Sync

Він говорить

The default sync handler maps CRUD to REST like so:

create → POST   /collection
read → GET   /collection[/id]
update → PUT   /collection/id
delete → DELETE   /collection/id

Тепер, оскільки я завжди займався розробкою інтерфейсів та був новим у Backbone, мені важко зрозуміти вищезазначене ... Я ніколи не використовував REST або будь-які інші протоколи на стороні сервера ...

Не могли б ви пояснити те саме простими словами (наприклад, як REST відображається, коли ми використовуємо Backbone.sync) Будь-який дуже простий приклад був би дуже корисним ...


Магістраль - це такий жахливо розроблений каркас. Так, давайте створимо фірмовий термін, який має співвідношення 1: 1 до значущого дієслова HTTP. Це покращить досвід розробників! Крім того, зробіть дієслова абсолютно негнучкими, оскільки очевидно, що будь-яка зроблена послуга RESTful використовувала найкращі практики щодо дієслів HTTP та об’єкта CRUD.
evanmcdonnal

Відповіді:


312

Якщо ви не проти, я почну з прояснення деяких формулювань. REST не є протоколом сам по собі, це просто спосіб використання протоколу HTTP. Стиль REST особливо корисний для API, як я сподіваюся, ви побачите. Коли API відповідає цьому стилю, він називається "RESTful". Якщо API, з яким ви працюєте, не є RESTful, вам доведеться внести багато змін до Backbone.sync, щоб змусити його працювати. Так що сподіваємось, що це так! :)

Протокол HTTP

Мені подобаються приклади, тому ось HTTP-запит, щоб отримати HTML для цієї сторінки:

GET /questions/18504235/understand-backbone-js-rest-calls HTTP/1.1
Host: stackoverflow.com

[Необов’язково] Якщо ви коли-небудь грали з командним рядком або терміналом, спробуйте запустити команду telnet stackoverflow.com 80та вставити вище, а потім кілька разів натиснути клавішу enter. Вуаля! HTML у всій його славі.

У цьому прикладі ...

  • GETє методом .
  • /questions/18504235/understand-backbone-js-rest-callsце шлях .
  • HTTP/1.1- це протокол .
  • Host: stackoverflow.comє прикладом заголовка .

Ваш браузер робить приблизно те саме, лише з більшою кількістю заголовків, щоб отримати HTML для цієї сторінки. Класно, так?

Оскільки ви працюєте в інтерфейсі, ви, напевно, бачили тег форми багато разів. Ось приклад одного:

<form action="/login" method="post">
    <input type="text" name="username" />
    <input type="password" name="password" />
    <input type="submit" name="submit" value="Log In" />
</form>

Коли ви надсилаєте цю форму разом із відповідними даними, ваш браузер надсилає запит приблизно такого вигляду:

POST /login HTTP/1.1
Host: stackoverflow.com

username=testndtv&password=zachrabbitisawesome123&submit=Log%20In

Є три відмінності між попереднім прикладом і цим.

  1. Метод тепер POST.
  2. Шлях тепер /login.
  3. Існує додаткова лінія, яка називається тілом .

Хоча є купа інших способів, ті , які використовуються в RESTful додатків POST, GET,PUT і DELETE. Це повідомляє серверу, який тип дії він повинен виконати з даними, не маючи для цього різних шляхів.

Назад до Backbone

Тож сподіваємось, тепер ви трохи більше розумієте, як працює HTTP. Але як це пов’язано з Backbone? Давай дізнаємось!

Ось невелика частина коду, яку ви можете знайти у програмі Backbone.

var BookModel = Backbone.Model.extend({
    urlRoot: '/books'
});
var BookCollection = Backbone.Collection.extend({
    model: BookModel
    , url: '/books'
});

Створити (POST)

Оскільки ми використовуємо RESTful API, це вся інформація, яку Backbone має мати можливість створювати, читати, оновлювати та видаляти всю інформацію про нашу книгу! Почнемо із створення нової книги. Достатньо такого коду:

var brandNewBook = new BookModel({ title: '1984', author: 'George Orwel' });
brandNewBook.save();

Backbone розуміє, що ви намагаєтеся створити нову книгу, і знає з інформації, яку вона отримала, зробити такий запит:

POST /books HTTP/1.1
Host: example.com

{"title":"1984","author":"George Orwel"}

Читати (ОТРИМАТИ)

Бачите, як легко це було? Але ми хочемо повернути цю інформацію в якийсь момент. Скажімо, ми побігли new BookCollection().fetch(). Магістральний б зрозуміти , що ви намагаєтеся прочитати в колекцію книг, і було б зробити наступний запит:

GET /books HTTP/1.1
Host: example.com

БАМ. Це просто. Але скажімо, ми хотіли отримати інформацію лише для однієї книги. Скажімо, книга No42. Скажімо, ми побігли new BookModel({ id: 42 }).fetch(). Магістральна бачить , що ви намагаєтеся прочитати в єдину книгу:

GET /books/42 HTTP/1.1
Host: example.com

Оновлення (PUT)

О боже, я щойно зрозумів, що неправильно написав ім’я містера Оруелла. Легко виправити!

brandNewBook.set('author', 'George Orwell');
brandNewBook.save();

Магістраль досить розумна, щоб знати, що, незважаючи на те brandNewBook, що її викликали , вона вже збережена. Тож він оновлює книгу:

PUT /books/84 HTTP/1.1
Host: example.com

{"title":"1984","author":"George Orwell"}

Видалити (ВИДАЛИТИ)

Нарешті, ви усвідомлюєте, що уряд відстежує кожен ваш крок, і вам потрібно поховати той факт, що ви прочитали 1984 рік. Напевно, пізно, але намагатися ніколи не завадить. Отже, ви біжите brandNewBook.destroy(), а Backbone стає розумним і розуміє, що ваша небезпека видаляє книгу з таким запитом:

DELETE /books/84 HTTP/1.1
Host: example.com

І його немає.

Інші корисні шматочки

Хоча ми багато говорили про те, що ми надсилаємо на сервер, нам, мабуть, слід також поглянути на те, що ми повертаємо. Повернемось до нашої книгозбірні. Якщо ви пам’ятаєте, ми подали GETзапит до /books. Теоретично нам слід повернути щось подібне:

[
    {"id":42,"author":"Douglas Adams","title":"The Hitchhiker's Guide to the Galaxy"}
    , {"id":3,"author":"J. R. R. Tolkien","title":"The Lord of the Rings: The Fellowship of the Ring"}
]

Нічого надто страшного. А ще краще, Backbone знає, як з цим впоратися нестандартно. Але що, якби ми трохи змінили його? Замість того, щоб idбути ідентифікаційним полем, це було bookId?

[
    {"bookId":42,"author":"Douglas Adams","title":"The Hitchhiker's Guide to the Galaxy"}
    , {"bookId":3,"author":"J. R. R. Tolkien","title":"The Lord of the Rings: The Fellowship of the Ring"}
]

Backbone робить так, що кожен API трохи відрізняється, і це нормально. Все, що вам потрібно зробити, це повідомити про це приблизно idAttributeтак:

var BookModel = Backbone.Model.extend({
    urlRoot: '/books'
    , idAttribute: 'bookId'
});

Вам потрібно лише додати цю інформацію до моделі, оскільки колекція все одно перевіряє модель. Тож просто так, Backbone розуміє ваш API! Навіть якщо я цього не роблю ...

Недоліком цього є те, що ви повинні пам’ятати про використання bookIdв певних випадках. Наприклад, там, де раніше ми new BookModel({ id: 42 }).fetch()завантажували дані про одну книгу, тепер нам доведеться використовувати new BookModel({ bookId: 42 }).fetch().


Сподіваємось, ви знайшли цю відповідь інформативною і не надто нестерпно нудною. Я розумію, що для багатьох протокол HTTP та архітектура RESTful не є найбільш захоплюючими темами, тому я намагався трохи оживити це. Я можу пошкодувати, що коли прочитаю все це пізніше, але зараз 2 ранку, тож я все одно подаю це.


5
Приємно читати. Також існує дієслово PATCH, яке підтримується Backbone backbonejs.org/#Model-save, але це, мабуть, не так корисно в огляді REST
nikoshr

2
І, за замовчуванням, методи POST / PUT надсилають свої корисні навантаження як JSON, а не як параметри, закодовані у формі
nikoshr

1
@SixteenStudio Радий, що міг допомогти!
ZachRabbit

4
Яка фантастична відповідь!
Джеймс Сефтон,

3
Це дивно. Набагато, набагато краще, ніж офіційна документація!
goodpixels

4

Припускаючи, що ви розумієте виклики ajax (POST, GET тощо до '/ collection' тощо).

Backbone використовує синхронізацію для маршрутизації деяких методів моделей та колекцій до викликів REST.

model/collection.fetch() => GET
model.save() => POST (isNew())
model.save() => PUT (!isNew())
model.destroy() => DELETE

collection.create() дзвінки model.save() (isNew()) => POST

Якщо ви передасте URL-адресу (/ колекцію), яку ви хочете використовувати, моделі / колекції, Backbone подбає про дзвінки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.