portaldacalheta.pt
  • Основен
  • Подвижен
  • Дизайн На Марката
  • Възходът На Дистанционното
  • Жизнен Цикъл На Продукта
Back-End

ActiveResource.js: Бързо изграждане на мощен JavaScript SDK за вашия JSON API



Вашата компания току-що стартира своя API и сега иска да изгради общност от потребители около нея. Знаете, че повечето от клиентите ви ще работят в JavaScript , тъй като услугите, които предоставя вашият API, улесняват клиентите да създават уеб приложения, вместо да пишат всичко сами - Twilio е добър пример за това.

Вие също знаете, че толкова просто, колкото и вашето RESTful API може би, потребителите ще искат да пуснат JavaScript пакет които ще направят цялото вдигане за тях. Те няма да искат да научат вашия API и сами да изградят всяка заявка, от която се нуждаят.



Така че изграждате библиотека около вашия API. Или може би просто пишете система за управление на състоянието за уеб приложение, което взаимодейства със собствения ви вътрешен API.



Така или иначе, не искате да се повтаряте отново и отново всеки път, когато CRUD някой от вашите API ресурси, или по-лошо, CRUD ресурс, свързан с тези ресурси. Това не е добре за управление на нарастващ SDK в дългосрочен план, нито е добро използване на вашето време.



Вместо това можете да използвате ActiveResource.js , JavaScript ORM система за взаимодействие с API. Създадох го, за да отговоря на нуждите, които имахме по проект: да създадем JavaScript SDK в възможно най-малко редове. Това даде възможност за максимална ефективност за нас и за нашата общност на разработчици.

Той се основава на принципите, стоящи зад простия ActiveRecord ORM на Ruby on Rails.



Принципи на JavaScript SDK

Има две идеи за Ruby on Rails, които ръководят дизайна на ActiveResource.js:

  1. „Конвенция за конфигурация:“ Направете някои предположения относно естеството на крайните точки на API. Например, ако имате Product ресурс, той съответства на /products крайна точка. По този начин времето не се изразходва многократно за конфигуриране на всяка от заявките на вашия SDK към вашия API. Разработчиците могат да добавят нови API ресурси със сложни CRUD заявки към вашия нарастващ SDK за минути, а не за часове.
  2. „Превъзнасяйте красивия код:“ Създател на Rails DHH го каза най-добре - има просто нещо страхотно в красивия код сам по себе си. ActiveResource.js обвива понякога грозни заявки в красив екстериор. Вече не е нужно да пишете персонализиран код, за да добавяте филтри и разбиване на страници и да включвате релации, вложени в релации в GET заявки. Нито трябва да конструирате POST и PATCH заявки, които вземат промени в свойствата на обекта и ги изпращат на сървъра за актуализиране. Вместо това просто извикайте метод на ActiveResource: Няма повече игра с JSON, за да получите искането, което искате, а само да го направите отново за следващото.

Преди да започнем

Важно е да се отбележи, че по време на настоящото писане ActiveResource.js работи само с API, написани според JSON: API стандарт .



Ако не сте запознати с JSON: API и искате да продължите, има много добри библиотеки за създаване на JSON: API сървър.

Въпреки това ActiveResource.js е по-скоро DSL, отколкото обвивка за един конкретен API стандарт. Интерфейсът, който използва за взаимодействие с вашия API, може да бъде разширен, така че бъдещите статии могат да обхващат как да използвате ActiveResource.js с вашия персонализиран API.



Настройване на нещата

За начало инсталирайте active-resource във вашия проект:

yarn add active-resource

Първата стъпка е да създадете ResourceLibrary за вашия API. Ще поставя всичките си ActiveResource в src/resources папка:



// /src/resources/library.js import { createResourceLibrary } from 'active-resource'; const library = createResourceLibrary('http://example.com/api/v1'); export default library;

Единственият задължителен параметър за createResourceLibrary е основният URL на вашия API.

php-utf-8

Какво ще създадем

Ще създадем JavaScript SDK библиотека за API на системата за управление на съдържанието. Това означава, че ще има потребители, публикации, коментари и известия.



Потребителите ще могат да четат, създават и редактират публикации; четете, добавяйте и изтривайте коментари (към публикации или към други коментари) и получавайте известия за нови публикации и коментари.

Няма да използвам конкретна библиотека за управление на изгледа (React, Angular и др.) Или състоянието (Redux и др.), Вместо да абстрахирам урока, за да взаимодействам само с вашия API чрез ActiveResource s.

Първият ресурс: Потребители

Ще започнем, като създадем User ресурс за управление на потребителите на CMS.

Първо, ние създаваме User ресурсен клас с някои attributes:

// /src/resources/User.js import library from './library'; class User extends library.Base { static define() { this.attributes('email', 'userName', 'admin'); } } export default library.createResource(User);

Да приемем засега, че имате крайна точка за удостоверяване, която след като потребителят изпрати имейла и паролата си, връща токен за достъп и идентификатора на потребителя. Тази крайна точка се управлява от някаква функция requestToken. След като получите удостоверения потребителски идентификатор, искате да заредите всички данни на потребителя:

import library from '/src/resources/library'; import User from '/src/resources/User'; async function authenticate(email, password) { let [accessToken, userId] = requestToken(email, password); library.headers = { Authorization: 'Bearer ' + accessToken }; return await User.find(userId); }

Зададох library.headers да има Authorization заглавка с accessToken така че всички бъдещи заявки от моя ResourceLibrary са упълномощени.

По-късен раздел ще обхване как да удостоверите потребител и да зададете маркера за достъп, използвайки само User ресурсен клас.

Последната стъпка от authenticate е заявка към User.find(id). Това ще направи заявка до /api/v1/users/:id и отговорът може да изглежда по следния начин:

{ 'data': { 'type': 'users', 'id': '1', 'attributes': { 'email': ' [email protected] ', 'user_name': 'user1', 'admin': false } } }

Отговорът от authenticate ще бъде екземпляр на User клас. Оттук можете да получите достъп до различните атрибути на удостоверения потребител, ако искате да ги покажете някъде в приложението.

let user = authenticate(email, password); console.log(user.id) // '1' console.log(user.userName) // user1 console.log(user.email) // [email protected] console.log(user.attributes()) /* { email: ' [email protected] ', userName: 'user1', admin: false } */

Всяко от имената на атрибутите ще стане camelCased, за да отговаря на типичните стандарти на JavaScript. Можете да получите всеки от тях директно като свойства на user обект или вземете всички атрибути, като извикате user.attributes().

какво е паралелност в програмирането

Добавяне на ресурсен индекс

Преди да добавим още ресурси, свързани с User клас, като известия, трябва да добавим файл, src/resources/index.js, който ще индексира всички наши ресурси. Това има две предимства:

  1. Това ще изчисти вноса ни, като ни позволи да деструктурираме src/resources за множество ресурси в един оператор за импортиране, вместо да се използват множество оператори за импортиране.
  2. Той ще инициализира всички ресурси в ResourceLibrary ние ще създадем, като извикаме library.createResource на всеки, което е необходимо на ActiveResource.js за изграждане на взаимоотношения.
// /src/resources/index.js import User from './User'; export { User };

Добавяне на свързан ресурс

Сега нека създадем свързан ресурс за User, | Notification. Първо създайте Notification клас, който belongsTo User клас:

// /src/resources/Notification.js import library from './library'; class Notification extends library.Base { static define() { this.belongsTo('user'); } } export default library.createResource(Notification);

След това го добавяме към индекса за ресурси:

// /src/resources/index.js import Notification from './Notification'; import User from './User'; export { Notification, User };

След това свържете известията с User клас:

// /src/resources/User.js class User extends library.Base { static define() { /* ... */ this.hasMany('notifications'); } }

След като върнем потребителя от authenticate, можем да заредим и покажем всички негови известия:

let notifications = await user.notifications().load(); console.log(notifications.map(notification => notification.message));

Също така можем да включим известия в оригиналната ни заявка за удостоверения потребител:

async function authenticate(email, password) { /* ... */ return await User.includes('notifications').find(userId); }

Това е една от многото опции, налични в DSL.

Преглед на DSL

Нека разгледаме това, което вече е възможно да поискаме само от кода, който сме написали досега.

Можете да заявите колекция от потребители или един потребител.

let users = await User.all(); let user = await User.first(); user = await User.last(); user = await User.find('1'); user = await User.findBy({ userName: 'user1' });

Можете да модифицирате заявката, като използвате възможни релационни методи:

// Query and iterate over all users User.each((user) => console.log(user)); // Include related resources let users = await User.includes('notifications').all(); // Only respond with user emails as the attributes users = await User.select('email').all(); // Order users by attribute users = await User.order({ email: 'desc' }).all(); // Paginate users let usersPage = await User.page(2).perPage(5).all(); // Filter users by attribute users = await User.where({ admin: true }).all(); users = await User .includes('notifications') .select('email', { notifications: ['message', 'createdAt'] }) .order({ email: 'desc' }) .where({ admin: false }) .perPage(10) .page(3) .all(); let user = await User .includes('notification') .select('email') .first();

Забележете, че можете да съставите заявката, като използвате произволно количество верижни модификатори и че можете да завършите заявката с .all(), .first(), .last() или .each().

Можете да изградите потребител локално или да го създадете на сървъра:

let user = User.build(attributes); user = await User.create(attributes);

След като имате постоянен потребител, можете да изпратите промени в него, за да бъдат запазени на сървъра:

user.email = ' [email protected] '; await user.save(); /* or */ await user.update({ email: ' [email protected] ' });

Можете също да го изтриете от сървъра:

await user.destroy();

Този основен DSL се разпростира и върху свързани ресурси, както ще демонстрирам в останалата част от урока. Сега можем бързо да приложим ActiveResource.js за създаване на останалата част от CMS: публикации и коментари.

Създаване на публикации

Създайте клас ресурс за Post и го свържете с User клас:

// /src/resources/Post.js import library from './library'; class Post extends library.Base { static define() { this.belongsTo('user'); } } export default library.createResource(Post); // /src/resources/User.js class User extends library.Base { static define() { /* ... */ this.hasMany('notifications'); this.hasMany('posts'); } }

Добавете Post към индекса на ресурсите също:

// /src/resources/index.js import Notification from './Notification'; import Post from './Post'; import User from './User'; export { Notification, Post, User };

След това завържете Post ресурс във форма за потребителите да създават и редактират публикации. Когато потребителят за първи път посети формуляра за създаване на нова публикация, Post ресурс ще бъде изграден и всеки път, когато формата се променя, ние прилагаме промяната към Post:

import Post from '/src/resources/Post'; let post = Post.build({ user: authenticatedUser }); onChange = (event) => { post.content = event.target.value; };

След това добавете onSubmit обратно извикване към формуляра, за да запишете публикацията на сървъра и да обработвате грешки, ако опитът за запис е неуспешен:

медийна заявка за отзивчив дизайн
onSubmit = async () => { try { await post.save(); /* successful, redirect to edit post form */ } catch { post.errors().each((field, error) => { console.log(field, error.message) }); } }

Редактиране на публикации

След като публикацията бъде запазена, тя ще бъде свързана с вашия API като ресурс на вашия сървър. Можете да разберете дали ресурсът се запазва на сървъра, като извикате persisted:

if (post.persisted()) { /* post is on server */ }

За персистиращи ресурси ActiveResource.js поддържа мръсни атрибути, тъй като можете да проверите дали някой атрибут на ресурс е променен от стойността му на сървъра.

Ако се обадите save() на персистиращ ресурс, той ще направи PATCH заявка, съдържаща само направените промени в ресурса, вместо да изпраща изцяло набора от атрибути и връзки на ресурса към сървъра.

Можете да добавяте проследени атрибути към ресурс, използвайки attributes декларация. Нека проследим промените в post.content:

// /src/resources/Post.js class Post extends library.Base { static define() { this.attributes('content'); /* ... */ } }

Сега, с поддържана от сървъра публикация, можем да редактираме публикацията и когато се кликне върху бутона за изпращане, запазете промените на сървъра. Също така можем да деактивираме бутона за изпращане, ако все още не са направени промени:

onEdit = (event) => { post.content = event.target.value; } onSubmit = async () => { try { await post.save(); } catch { /* display edit errors */ } } disableSubmitButton = () => { return !post.changed(); }

Има методи за управление на единична връзка като post.user(), ако искахме да променим потребителя, свързан с публикация:

await post.updateUser(user);

Това е еквивалентно на:

await post.update({ user });

Ресурсът за коментари

Сега създайте ресурсен клас Comment и го свържете с Post. Не забравяйте нашето изискване коментарите да бъдат в отговор на публикация или друг коментар, така че съответният ресурс за коментар е полиморфен:

// /src/resources/Comment.js import library from './library'; class Comment extends library.Base { static define() { this.attributes('content'); this.belongsTo('resource', { polymorphic: true, inverseOf: 'replies' }); this.belongsTo('user'); this.hasMany('replies', { as: 'resource', className: 'Comment', inverseOf: 'resource' }); } } export default library.createResource(Comment);

Не забравяйте да добавите Comment до /src/resources/index.js както добре.

Ще трябва да добавим ред към Post клас също:

// /src/resources/Post.js class Post extends library.Base { static define() { /* ... */ this.hasMany('replies', { as: 'resource', className: 'Comment', inverseOf: 'resource' }); } }

inverseOf опцията е предадена на hasMany определение за replies показва, че тази връзка е обратна на полиморфната belongsTo определение за resource. inverseOf свойството на връзките често се използват при извършване на операции между връзки. Обикновено това свойство ще се определя автоматично чрез името на класа, но тъй като полиморфните връзки могат да бъдат един от множество класове, трябва да дефинирате inverseOf изберете себе си, за да могат полиморфните връзки да имат същата функционалност като нормалните.

Управление на коментари за публикации

Същият DSL, който се прилага за ресурси, се отнася и за управлението на свързани ресурси. След като създадохме връзките между публикации и коментари, има редица начини да управляваме тази връзка.

Можете да добавите нов коментар към публикация:

onSubmitComment = async (event) => { let comment = await post.replies().create({ content: event.target.value, user: user }); }

Можете да добавите отговор към коментар:

onSubmitReply = async (event) => { let reply = await comment.replies().create({ content: event.target.value, user: user }); }

Можете да редактирате коментар:

onEditComment = async (event) => { await comment.update({ content: event.target.value }); }

Можете да премахнете коментар от публикация:

onDeleteComment = async (comment) => { await post.replies().delete(comment); }

Показване на публикации и коментари

SDK може да се използва за показване на страничен списък с публикации и когато се щракне върху публикация, публикацията се зарежда на нова страница с всички нейни коментари:

import { Post } from '/src/resources'; let postsPage = await Post .order({ createdAt: 'desc' }) .select('content') .perPage(10) .all();

Горната заявка ще извлече 10-те най-скорошни публикации и за оптимизиране единственият атрибут, който се зарежда, е техният content

Ако потребителят щракне върху бутон, за да премине към следващата страница на публикациите, манипулаторът на промени ще извлече следващата страница. Тук също деактивираме бутона, ако няма следващи страници.

onClickNextPage = async () => { postsPage = await postsPage.nextPage(); if (!postsPage.hasNextPage()) { /* disable next page button */ } };

Когато се кликне върху връзка към публикация, ние отваряме нова страница, като зареждаме и показваме публикацията с всички нейни данни, включително нейните коментари - известни като отговори, както и отговори на тези отговори:

import { Post } from '/src/resources'; onClick = async (postId) => { let post = await Post.includes({ replies: 'replies' }).find(postId); console.log(post.content, post.createdAt); post.replies().target().each(comment => { console.log( comment.content, comment.replies.target().map(reply => reply.content).toArray() ); }); }

Обажда се .target() на hasMany връзка като post.replies() ще върне ActiveResource.Collection на коментари, които са били заредени и съхранявани локално.

Това разграничение е важно, защото post.replies().target().first() ще върне първия зареден коментар. За разлика от тях, post.replies().first() ще върне обещание за един коментар, поискан от GET /api/v1/posts/:id/replies.

основните външни потребители на бизнес планове са

Можете също така да поискате отговорите за публикация отделно от заявката за самата публикация, което ви позволява да модифицирате заявката си. Можете да веригирате модификатори като order, select, includes, where, perPage, page при заявка hasMany взаимоотношения, точно както можете при заявка на самите ресурси.

import { Post } from '/src/resources'; onClick = async (postId) => { let post = await Post.find(postId); let userComments = await post.replies().where({ user: user }).perPage(3).all(); console.log('Your comments:', userComments.map(comment => comment.content).toArray()); }

Модифициране на ресурси, след като са поискани

Понякога искате да вземете данните от сървъра и да ги промените, преди да ги използвате. Например, можете да увиете post.createdAt в moment() обект, така че да можете да покажете удобна за потребителя дата и час за потребителя за това кога е създадена публикацията:

// /src/resources/Post.js import moment from 'moment'; class Post extends library.Base { static define() { /* ... */ this.afterRequest(function() { this.createdAt = moment(this.createdAt); }); } }

Неизменност

Ако работите със система за управление на състоянието, която благоприятства неизменяемите обекти, цялото поведение в ActiveResource.js може да бъде направено неизменяемо чрез конфигуриране на библиотеката с ресурси:

// /src/resources/library.js import { createResourceLibrary } from 'active-resource'; const library = createResourceLibrary( 'http://example.com/api/v1', { immutable: true } ); export default library;

Circling Back: Свързване на системата за удостоверяване

За да приключите, ще ви покажа как да интегрирате вашата система за удостоверяване на потребителя във вашия User ActiveResource.

Преместете системата си за удостоверяване на маркера в крайната точка на API /api/v1/tokens. Когато имейл и парола на потребител са изпратени до тази крайна точка, в отговор ще бъдат изпратени удостоверените данни на потребителя плюс токенът за упълномощаване.

Създайте Token ресурсен клас, който принадлежи към User:

// /src/resources/Token.js import library from './library'; class Token extends library.Base { static define() { this.belongsTo('user'); } } export default library.createResource(Token);

Добавете Token до /src/resources/index.js.

След това добавете статичен метод authenticate към вашия User ресурсен клас и свързват User до Token:

// /src/resources/User.js import library from './library'; import Token from './Token'; class User { static define() { /* ... */ this.hasOne('token'); } static async authenticate(email, password) { let user = this.includes('token').build({ email, password }); let authUser = await this.interface().post(Token.links().related, user); let token = authUser.token(); library.headers = { Authorization: 'Bearer ' + token.id }; return authUser; } }

Този метод използва resourceLibrary.interface(), който в този случай е интерфейсът JSON: API, за изпращане на потребител до /api/v1/tokens. Това е валидно: Крайна точка в JSON: API не изисква единствените типове, публикувани в и от нея, да са тези, на които е кръстено. Така че заявката ще бъде:

{ 'data': { 'type': 'users', 'attributes': { 'email': ' [email protected] ', 'password': 'password' } } }

Отговорът ще бъде удостовереният потребител с включен токен за удостоверяване:

{ 'data': { 'type': 'users', 'id': '1', 'attributes': { 'email': ' [email protected] ', 'user_name': 'user1', 'admin': false }, 'relationships': { 'token': { 'data': { 'type': 'tokens', 'id': 'Qcg6yI1a5qCxXgKWtSAbZ2MIHFChHAq0Vc1Lo4TX', } } } }, 'included': [{ 'type': 'tokens', 'id': 'Qcg6yI1a5qCxXgKWtSAbZ2MIHFChHAq0Vc1Lo4TX', 'attributes': { 'expires_in': 3600 } }] }

След това използваме token.id да зададем библиотеката на Authorization и върнете потребителя, което е същото като искането на потребителя чрез User.find() както правехме преди.

Сега, ако се обадите User.authenticate(email, password), ще получите удостоверен потребител в отговор и всички бъдещи заявки ще бъдат упълномощени с токен за достъп.

ActiveResource.js Активира бързото разработване на SDK за JavaScript

В този урок изследвахме начините, по които ActiveResource.js може да ви помогне бързо да изградите JavaScript SDK за управление на вашите API ресурси и техните различни, понякога сложни, свързани ресурси. Можете да видите всички тези функции и по-документирани в README за ActiveResource.js .

Надявам се, че сте се насладили на лекотата, с която могат да се извършват тези операции, и че ще използвате (а може би дори ще допринесете) моята библиотека за вашите бъдещи проекти, ако отговаря на вашите нужди. В духа на отворения код, PR винаги са добре дошли!

Разбиране на основите

Какво означава SDK?

SDK означава „комплект за разработка на софтуер“, което в контекст на JavaScript често означава библиотека за взаимодействие със специфичен REST API.

Какво означава съкращението ORM?

ORM означава „обектно-релационно картографиране“, техника за работа с обекти, без да се налага да мислим откъде идват или как се съхраняват. Например, ORM библиотека може да абстрахира API или необходимостта от знания за SQL, в зависимост от слоя, в който се използва.

Какво е CRUD услуга?

CRUD услуга, напр. основен REST API, е този, който осигурява интерфейс за извършване на операции „създаване, четене, актуализиране и изтриване“. С други думи, той позволява основни операции за съхранение на данни, съответстващи на SQL командите INSERT, SELECT, UPDATE и DELETE и на HTTP глаголите POST, GET, PUT / PATCH и DELETE.

Какво прави API?

API осигурява абстракция на услуга, улесняваща работата с нея, обикновено с цел да бъде достъпна за по-широка група програмисти. Например API на Trello ви позволява програмно да създавате нови карти Trello чрез HTTP заявки.

За какво се използва API ключ?

Ключът на API е таен маркер, използван за формулиране на заявки, позволяващ на доставчика на услуги на API да идентифицира положително заявителя, ако приеме, че остава таен.

Какво означава управление на съдържанието?

Управлението на съдържанието обикновено се отнася до създаване и организиране на текстово съдържание, което да бъде публикувано в интранет или в интернет. Най-популярната система за управление на съдържанието (CMS) през последните няколко години е WordPress.

Какво е ORM база данни?

Това е съвпадение на термините, но вероятно се отнася до RDBMS, например SQL Server, MySQL или PostgreSQL. ORM инструментите понякога помагат да се съпоставят обектите с SQL back-end. ActiveResource.js абстрахира различен слой, като съпоставя обекти с крайни точки на REST API.

Java в облака: Урок за настройка на непрекъсната интеграция

Back-End

Java в облака: Урок за настройка на непрекъсната интеграция
Управление на продукти, овластено от предприемаческия начин на мислене

Управление на продукти, овластено от предприемаческия начин на мислене

Жизнен Цикъл На Продукта

Популярни Публикации
Създавайте данни от случаен шум с генерални състезателни мрежи
Създавайте данни от случаен шум с генерални състезателни мрежи
Миналото все още присъства - преглед на вечния дизайн
Миналото все още присъства - преглед на вечния дизайн
Финансово бедствие в криза: Не можете да предскажете, можете да подготвите
Финансово бедствие в криза: Не можете да предскажете, можете да подготвите
Бруталистки уеб дизайн, минималистичен уеб дизайн и бъдещето на Web UX
Бруталистки уеб дизайн, минималистичен уеб дизайн и бъдещето на Web UX
Разширени съвети и хакове за презентация на PowerPoint
Разширени съвети и хакове за презентация на PowerPoint
 
Архитект отпред
Архитект отпред
Студената технологична война: все още тук и все още се използва
Студената технологична война: все още тук и все още се използва
Въведение в Apache Spark с примери и случаи на употреба
Въведение в Apache Spark с примери и случаи на употреба
Комодитизирани смартфони: Привеждане на 4G в развиващите се страни
Комодитизирани смартфони: Привеждане на 4G в развиващите се страни
Как да създам API за Secure Node.js GraphQL
Как да създам API за Secure Node.js GraphQL
Популярни Публикации
  • как да получа номера на нечия кредитна карта
  • разлика в s и c корпорация
  • вземете елемент от клас angularjs
  • набиране на частен капитал за недвижими имоти
  • как работят двигателите на физиката
  • колко време е необходимо за сертифициране на aws
  • използвайте raspberry pi като уеб сървър
Категории
  • Подвижен
  • Дизайн На Марката
  • Възходът На Дистанционното
  • Жизнен Цикъл На Продукта
  • © 2022 | Всички Права Запазени

    portaldacalheta.pt