SlideShare una empresa de Scribd logo
1 de 39
Descargar para leer sin conexión
ANGULARJS
BACKEND
STORIES
How to build a backend-ready app
WITHOUT BACKEND
Wearing multiple hats at Narada Robotics startup, from coding to whatever else…
Main interests - mobile development
IN LOVE WITH ANGULARJS
Enrique Oriol
CTO @ Narada Robotics
blog.enriqueoriol.com @enrique.oriol
SCENARIO
I want you to develop my frontend
I’ll provide you with an API REST
SCENARIO
I want you to develop my frontend
I’ll provide you with an API REST
BACKEND STORIES 5
URLS TO LOCAL JSONS
Of course we can use urls to local JSON files, but…
We cannot use POST, PUT...
We cannot use response codes
We cannot access headers
So we cannot really prepare client side API connections
@enrique.oriol
WHAT CAN WE DO?
MOCKING THE SERVER
What we will cover:
URL DEFINITIONS01
CREATING JSON FIXTURES02
USING $HTTPBACKEND03
USING $RESOURCE04
DYNAMIC RESPONSES05
BACKEND PERSISTENCE06
BACKEND STORIES 8
CAUTION
This is NOT intended to be used in PRODUCTION
@enrique.oriol
BACKEND STORIES 9
Why not Node.js mock?
It is just an alternative to any other mock server
It runs at the same JS VM, so it does not need a public
endpoint somewhere
Think about sending the results to a client in the case of a
hybrid app
@enrique.oriol
BACKEND STORIES 10
You can download code here:
https://github.com/kaikcreator/UserRanking
And play with the results here:
http://kaikcreator.github.io/UserRanking/
EXAMPLE APP
We will use User Ranking app as
example
@enrique.oriol
QUICK OVERVIEW USER RANKING
Require Following Integration With API
NON AUTHENTICATED
CREATE USER - POST user endpoint
USERS RANKING - GET users endpoint
AUTHENTICATED
UPDATE USER - PUT user endpoint
URL DEFINITION
Let’s organize our code
BACKEND STORIES 13
URL DEFINITION
app/services/url/URLModule.js
angular.module('userRanking.urlsModule', [])
.constant('urlConst', (function(){
var protocol = 'http://';
var domain = 'www.userRanking.com';
var base = '/api';
var version = '/v1';
var placeholders = {
userId: '[userId]'
}
return {
user: protocol + domain + base + version + '/user/' + placeholders.userId,
users: protocol + domain + base + version + '/users',
placeholders: placeholders
};
})())
@enrique.oriol
BACKEND STORIES 14
URL DEFINITION
app/services/url/URLModule.js
.factory('urls', ['urlConst', function(urlConst){
var urls = angular.copy(urlConst);
var replacePlaceholders = function(url, placeholders){
for(var key in placeholders){
url = url.replace(urlConst.placeholders[key], placeholders[key]);
}
return url;
};
//generate dinamic urls here
urls.user = function(id){
return replacePlaceholders(urlConst.user, {userId: id});
};
return urls;
}]);
@enrique.oriol
BACKEND STORIES 15
URL DEFINITION
This Approach
EASY TO EXTEND
WITH MORE
ENDPOINTS
ISOLATES URL
DETAILS FROM
OTHER SERVICES
@enrique.oriol
CREATING JSON
FIXTURES
We should agree in the models
BACKEND STORIES 17
CREATING JSON FIXTURES
How a user will look like
{
id: userId,
name: username,
image: urlToUserImage,
rating: userRating
}
@enrique.oriol
BACKEND STORIES 18
CREATING JSON FIXTURES
app/fixtures/users.json
[
{
"id": "1",
"name": "Peter",
"image": "user1.png",
"points": 150
},
.
.
.
{
"id": "6",
"name": "Travis",
"image": "user6.png",
"points": 100
}
]
@enrique.oriol
E2E
$HttpBackend
As a mechanism not to test, but to mock our server
BACKEND STORIES 20
e2e $httpBackend
https://docs.angularjs.org/api/ngMockE2E/service/$httpBackend
1. download
Installation
$ bower install angular-mocks
2. include source
<!-- mock server -->
<script src="bower_components/angular-mocks/angular-mocks.js"></script>
3. include module
angular.module('app', ['ngMockE2E']);
@enrique.oriol
BACKEND STORIES 21
e2e $httpBackend
https://docs.angularjs.org/api/ngMockE2E/service/$httpBackend
When URL: return object with responds & passthrough methods
Basics
when( method, url, [data], [headers], [keys] );
Responds
Passthrough
$httpBackend.when(‘GET’, url).respond({} / [])
$httpBackend.when(‘GET’, url).respond(function(method, url, data, headers, params){})
$httpBackend.when(‘GET’, url).passThrough()
@enrique.oriol
BACKEND STORIES 22
e2e $httpBackend
app/services/mock/MockServerModule.js
angular.module('userRanking.mockServerModule', ['ngMockE2E', 'userRanking.urlsModule'])
.run(['$httpBackend', 'urls', function($httpBackend, urls){
/*mocked data*/
$httpBackend.whenGET(urls.users)
.respond([
{ "id":"5", "name":"Alex", "image":"user5.png", "points": 210},
{ "id":"6", "name":"Travis", "image":"user6.png", "points": 100}
]);
}])
@enrique.oriol
$resource
As a mechanism to load local JSON files
BACKEND STORIES 24
$resource
https://docs.angularjs.org/api/ngResource/service/$resource
1. download
Installation
$ bower install angular-resource
2. include source
<!-- mock server -->
<script src="bower_components/angular-resource/angular-resource.js"></script>
3. include module
angular.module('app', ['ngResource']);
@enrique.oriol
BACKEND STORIES 25
$resource: return object with different methods, that populates async
Usage
$resource(url, [paramDefaults], [actions], options)
Returned object methods
$resource
https://docs.angularjs.org/api/ngResource/service/$resource
{ 'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'}
};
@enrique.oriol
BACKEND STORIES 26
$resource
app/services/mock/MockServerModule.js
angular.module('userRanking.mockServerModule', ['ngMockE2E','ngResource', 'userRanking.urlsModule'])
.constant('fixturePaths', {
"users": "fixtures/users.json"
})
.run(['$httpBackend', 'urls', 'fixturePaths', '$resource', function($httpBackend, urls, fixturePaths, $resource){
/* allow local calls */
$httpBackend.whenGET(/fixtures/.*/).passThrough();
/*mocked data*/
$httpBackend.whenGET(urls.users).respond( $resource(fixturePaths.users).query() );
}])
@enrique.oriol
BACKEND STORIES 27
If you perform a $http call just after app boostrap, it’s possible that $resource is
not already populated, returning an empty value.
In that case you should perform some additional trick, always trying to perform
all the stuff in MockServerModule, so it’s easier to “shut down” mock server
when real server comes to life.
You can see a decorator approach in the example code available on github.
REMEMBER that $resource
is populated ASYNC
$resource
@enrique.oriol
Dynamic
responses
The power behind mocking server with E2E
$httpBackend
BACKEND STORIES 29
Dynamic responses
Using function inside $httpBackend.respond
<!-- mocked data -->
$httpBackend.whenGET(urls.users).respond( $resource(fixturePaths.users).query() );
/*mocked data*/
var usersResource = $resource(fixturePaths.users).query();
$httpBackend.whenGET(urls.users).respond(function(method, url, data, headers){
return [200, usersResource, {}];
});
Changing this:
Into this:
Gives us access to url, data and headers, so our response can be dynamic
@enrique.oriol
BACKEND STORIES 30
Dynamic responses
We can perform data validation, and return custom headers
.run(['$httpBackend', 'urls', 'fixturePaths', '$resource', function($httpBackend, urls, fixturePaths, $resource){
/*...previous stuff...*/
/* regex allowing any user id in user url*/
var anyUserUrl = new RegExp(urls.user('.*'));
/*mock POST rx of a new user, and return auth token*/
$httpBackend.whenPOST(anyUserUrl).respond(function(method, url, data, headers){
data = angular.fromJson(data);
if(data.name === undefined || !angular.isString(data.name) || data.name.length === 0){ return [400, null, null]; }
else{
var user = {
"id": "7",
"name": data.name,
"points": 0
};
return [200, user, {Authorization: "1234567890asdfghjklzxcvbnm"}];
}
});
}])
@enrique.oriol
BACKEND STORIES 31
Dynamic responses
We lack persistence
.run(['$httpBackend', 'urls', 'fixturePaths', '$resource', function($httpBackend, urls, fixturePaths, $resource){
/*...previous stuff...*/
/*mock POST rx of a new user, and return auth token*/
$httpBackend.whenPUT(anyUserUrl).respond(
function(method, url, data, headers){
data = angular.fromJson(data);
if(headers['Authorization'] !== "Token 1234567890asdfghjklzxcvbnm"){
return [401, null, null];
}
else if(data.name === undefined && data.points === undefined && data.image ===undefined){
return [400, null, null];
}
else{
/*here we need to return updated data, so our app can reflect changes*/
var user = {...};
return [200, user, {}];
}
});
}])
@enrique.oriol
Backend persistence
Completing the experience with localStorage
BACKEND STORIES 33
Write in LS
$window.localStorage['myKey'] = angular.toJson(myData);
Read from LS
var data = angular.fromJson($window.localStorage['myKey']);
Usage
Backend persistence
Local Storage
@enrique.oriol
BACKEND STORIES 34
.constant('lsMock', {
"users": "ls-cached-users"
})
.factory('mockedUsers', ['$window', '$resource', 'fixturePaths', 'lsMock',
function($window, $resource, fixturePaths, lsMock){
var service = {};
service.list = angular.fromJson($window.localStorage[lsMock.users]);
if(!service.list || service.list.length === 0){
service.list = $resource(fixturePaths.users).query();
}
service.save = function(){
$window.localStorage[lsMock.users] = angular.toJson(service.list);
};
service.add = function(user){
service.list.push(user);
service.save();
};
Backend persistence
Define a service to handle with cached users
service.update = function(user){
for(var i=0; i<service.list.length; i++){
if(service.list[i].id == user.id){
service.list[i].points = user.points;
service.save();
return;
}
}
};
service.getById = function(userId){
for(var i=0; i<service.list.length; i++){
if(service.list[i].id == userId){
return service.list[i];
}
}
return null;
};
return service;
}])
@enrique.oriol
BACKEND STORIES 35
.run(['$httpBackend', '$resource', 'urls', 'mockedUsers', function($httpBackend, $resource, urls, mockedUsers){
/* local calls */
$httpBackend.whenGET(/fixtures/.*/).passThrough();
/* regex allowing any user id in user url*/
var anyUserUrl = new RegExp(urls.user('.*'));
/*mocked users list*/
$httpBackend.whenGET(urls.users).respond(function(method, url, data, headers){
return [200, mockedUsers.list];
});
Backend persistence
Using our service in mock server - whenGET
@enrique.oriol
BACKEND STORIES 36
/* mock update user*/
$httpBackend.whenPUT(anyUserUrl).respond(
function(method, url, data, headers){
data = angular.fromJson(data);
var userId = url.replace(urls.user(''), '');
if(!data.id) {data.id = userId;}
if(headers['Authorization'] !== "Token 1234567890asdfghjklzxcvbnm"){
return [401, null, null];
}
else if(data.name === undefined && data.points === undefined && data.image ===undefined){
return [400, null, null];
}
else{
mockedUsers.update(data);
data = mockedUsers.getById(userId);
return [200, data, {}];
}
});
Backend persistence
Using our service in mock server - - whenPUT
@enrique.oriol
BACKEND STORIES 37
/* mock new user*/
$httpBackend.whenPOST(anyUserUrl).respond(
function(method, url, data, headers){
data = angular.fromJson(data);
if(data.name === undefined || !angular.isString(data.name) || data.name.length === 0){
return [400, null, null];
}
else{
var user = {
"id": ''+ mockedUsers.list.length,
"name": data.name,
"points": 0
};
mockedUsers.add(user);
return [200, user, {Authorization: "1234567890asdfghjklzxcvbnm"}];
}
});
}])
Backend persistence
Using our service in mock server - - whenPOST
@enrique.oriol
You’re ready
Time to play with code
http://kaikcreator.github.io/UserRanking/
THANK YOU!
http://lnkdin.me/enriqueoriol
blog.enriqueoriol.com
@enrique.oriol

Más contenido relacionado

La actualidad más candente

An introduction to Ember.js
An introduction to Ember.jsAn introduction to Ember.js
An introduction to Ember.jscodeofficer
 
Hey, I just met AngularJS, and this is crazy, so here’s my JavaScript, let’s ...
Hey, I just met AngularJS, and this is crazy, so here’s my JavaScript, let’s ...Hey, I just met AngularJS, and this is crazy, so here’s my JavaScript, let’s ...
Hey, I just met AngularJS, and this is crazy, so here’s my JavaScript, let’s ...Alessandro Nadalin
 
Intro to computer vision in .net
Intro to computer vision in .netIntro to computer vision in .net
Intro to computer vision in .netStephen Lorello
 
Promises are so passé - Tim Perry - Codemotion Milan 2016
Promises are so passé - Tim Perry - Codemotion Milan 2016Promises are so passé - Tim Perry - Codemotion Milan 2016
Promises are so passé - Tim Perry - Codemotion Milan 2016Codemotion
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patternsSamuel ROZE
 
2011 a grape odyssey
2011   a grape odyssey2011   a grape odyssey
2011 a grape odysseyMike Hagedorn
 
Intro to Ember.js
Intro to Ember.jsIntro to Ember.js
Intro to Ember.jsJay Phelps
 
描画とビジネスをクリーンに分ける(公開用)
描画とビジネスをクリーンに分ける(公開用)描画とビジネスをクリーンに分ける(公開用)
描画とビジネスをクリーンに分ける(公開用)Kenji Tanaka
 
Building an angular application -1 ( API: Golang, Database: Postgres) v1.0
Building an angular application -1 ( API: Golang, Database: Postgres) v1.0Building an angular application -1 ( API: Golang, Database: Postgres) v1.0
Building an angular application -1 ( API: Golang, Database: Postgres) v1.0Frost
 
iPhone Appleless Apps
iPhone Appleless AppsiPhone Appleless Apps
iPhone Appleless AppsRemy Sharp
 
前端MVC 豆瓣说
前端MVC 豆瓣说前端MVC 豆瓣说
前端MVC 豆瓣说Ting Lv
 
RubyMotion
RubyMotionRubyMotion
RubyMotionMark
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the FinishYehuda Katz
 
Turn your spaghetti code into ravioli with JavaScript modules
Turn your spaghetti code into ravioli with JavaScript modulesTurn your spaghetti code into ravioli with JavaScript modules
Turn your spaghetti code into ravioli with JavaScript modulesjerryorr
 
Webapps without the web
Webapps without the webWebapps without the web
Webapps without the webRemy Sharp
 

La actualidad más candente (20)

Angularjs
AngularjsAngularjs
Angularjs
 
An introduction to Ember.js
An introduction to Ember.jsAn introduction to Ember.js
An introduction to Ember.js
 
Sane Async Patterns
Sane Async PatternsSane Async Patterns
Sane Async Patterns
 
jQuery for web development
jQuery for web developmentjQuery for web development
jQuery for web development
 
Hey, I just met AngularJS, and this is crazy, so here’s my JavaScript, let’s ...
Hey, I just met AngularJS, and this is crazy, so here’s my JavaScript, let’s ...Hey, I just met AngularJS, and this is crazy, so here’s my JavaScript, let’s ...
Hey, I just met AngularJS, and this is crazy, so here’s my JavaScript, let’s ...
 
Intro to computer vision in .net
Intro to computer vision in .netIntro to computer vision in .net
Intro to computer vision in .net
 
Frontin like-a-backer
Frontin like-a-backerFrontin like-a-backer
Frontin like-a-backer
 
Promises are so passé - Tim Perry - Codemotion Milan 2016
Promises are so passé - Tim Perry - Codemotion Milan 2016Promises are so passé - Tim Perry - Codemotion Milan 2016
Promises are so passé - Tim Perry - Codemotion Milan 2016
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
 
2011 a grape odyssey
2011   a grape odyssey2011   a grape odyssey
2011 a grape odyssey
 
Intro to Ember.js
Intro to Ember.jsIntro to Ember.js
Intro to Ember.js
 
描画とビジネスをクリーンに分ける(公開用)
描画とビジネスをクリーンに分ける(公開用)描画とビジネスをクリーンに分ける(公開用)
描画とビジネスをクリーンに分ける(公開用)
 
Building an angular application -1 ( API: Golang, Database: Postgres) v1.0
Building an angular application -1 ( API: Golang, Database: Postgres) v1.0Building an angular application -1 ( API: Golang, Database: Postgres) v1.0
Building an angular application -1 ( API: Golang, Database: Postgres) v1.0
 
iPhone Appleless Apps
iPhone Appleless AppsiPhone Appleless Apps
iPhone Appleless Apps
 
前端MVC 豆瓣说
前端MVC 豆瓣说前端MVC 豆瓣说
前端MVC 豆瓣说
 
Chainable datasource
Chainable datasourceChainable datasource
Chainable datasource
 
RubyMotion
RubyMotionRubyMotion
RubyMotion
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 
Turn your spaghetti code into ravioli with JavaScript modules
Turn your spaghetti code into ravioli with JavaScript modulesTurn your spaghetti code into ravioli with JavaScript modules
Turn your spaghetti code into ravioli with JavaScript modules
 
Webapps without the web
Webapps without the webWebapps without the web
Webapps without the web
 

Similar a How to build an AngularJS backend-ready app WITHOUT BACKEND

CFUGbe talk about Angular JS
CFUGbe talk about Angular JSCFUGbe talk about Angular JS
CFUGbe talk about Angular JSAlwyn Wymeersch
 
Building an End-to-End AngularJS Application
Building an End-to-End AngularJS ApplicationBuilding an End-to-End AngularJS Application
Building an End-to-End AngularJS ApplicationDan Wahlin
 
How to implement authorization in your backend with AWS IAM
How to implement authorization in your backend with AWS IAMHow to implement authorization in your backend with AWS IAM
How to implement authorization in your backend with AWS IAMProvectus
 
AngularJS for Java Developers
AngularJS for Java DevelopersAngularJS for Java Developers
AngularJS for Java DevelopersLoc Nguyen
 
Authenticating and Securing Node.js APIs
Authenticating and Securing Node.js APIsAuthenticating and Securing Node.js APIs
Authenticating and Securing Node.js APIsJimmy Guerrero
 
Angular data binding by Soft Solutions4U
Angular data binding by Soft Solutions4UAngular data binding by Soft Solutions4U
Angular data binding by Soft Solutions4Usharsen
 
Do you want a SDK with that API? (Nordic APIS April 2014)
Do you want a SDK with that API? (Nordic APIS April 2014)Do you want a SDK with that API? (Nordic APIS April 2014)
Do you want a SDK with that API? (Nordic APIS April 2014)Nordic APIs
 
Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications  Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications Juliana Lucena
 
A gently introduction to AngularJS
A gently introduction to AngularJSA gently introduction to AngularJS
A gently introduction to AngularJSGregor Woiwode
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecturepostrational
 
Angular Tutorial Freshers and Experienced
Angular Tutorial Freshers and ExperiencedAngular Tutorial Freshers and Experienced
Angular Tutorial Freshers and Experiencedrajkamaltibacademy
 
Headless Drupal en pratique
Headless Drupal en pratiqueHeadless Drupal en pratique
Headless Drupal en pratiqueSimon Morvan
 
Django + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoDjango + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoJavier Abadía
 
Good karma: UX Patterns and Unit Testing in Angular with Karma
Good karma: UX Patterns and Unit Testing in Angular with KarmaGood karma: UX Patterns and Unit Testing in Angular with Karma
Good karma: UX Patterns and Unit Testing in Angular with KarmaExoLeaders.com
 
Heroku pop-behind-the-sense
Heroku pop-behind-the-senseHeroku pop-behind-the-sense
Heroku pop-behind-the-senseBen Lin
 
Angular.js Primer in Aalto University
Angular.js Primer in Aalto UniversityAngular.js Primer in Aalto University
Angular.js Primer in Aalto UniversitySC5.io
 
Data models in Angular 1 & 2
Data models in Angular 1 & 2Data models in Angular 1 & 2
Data models in Angular 1 & 2Adam Klein
 

Similar a How to build an AngularJS backend-ready app WITHOUT BACKEND (20)

Angular Workshop_Sarajevo2
Angular Workshop_Sarajevo2Angular Workshop_Sarajevo2
Angular Workshop_Sarajevo2
 
CFUGbe talk about Angular JS
CFUGbe talk about Angular JSCFUGbe talk about Angular JS
CFUGbe talk about Angular JS
 
Building an End-to-End AngularJS Application
Building an End-to-End AngularJS ApplicationBuilding an End-to-End AngularJS Application
Building an End-to-End AngularJS Application
 
How to implement authorization in your backend with AWS IAM
How to implement authorization in your backend with AWS IAMHow to implement authorization in your backend with AWS IAM
How to implement authorization in your backend with AWS IAM
 
AngularJS for Java Developers
AngularJS for Java DevelopersAngularJS for Java Developers
AngularJS for Java Developers
 
Authenticating and Securing Node.js APIs
Authenticating and Securing Node.js APIsAuthenticating and Securing Node.js APIs
Authenticating and Securing Node.js APIs
 
Angular data binding by Soft Solutions4U
Angular data binding by Soft Solutions4UAngular data binding by Soft Solutions4U
Angular data binding by Soft Solutions4U
 
Do you want a SDK with that API? (Nordic APIS April 2014)
Do you want a SDK with that API? (Nordic APIS April 2014)Do you want a SDK with that API? (Nordic APIS April 2014)
Do you want a SDK with that API? (Nordic APIS April 2014)
 
Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications  Ember.js - A JavaScript framework for creating ambitious web applications
Ember.js - A JavaScript framework for creating ambitious web applications
 
A gently introduction to AngularJS
A gently introduction to AngularJSA gently introduction to AngularJS
A gently introduction to AngularJS
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecture
 
JavaScript Promise
JavaScript PromiseJavaScript Promise
JavaScript Promise
 
Node.js server-side rendering
Node.js server-side renderingNode.js server-side rendering
Node.js server-side rendering
 
Angular Tutorial Freshers and Experienced
Angular Tutorial Freshers and ExperiencedAngular Tutorial Freshers and Experienced
Angular Tutorial Freshers and Experienced
 
Headless Drupal en pratique
Headless Drupal en pratiqueHeadless Drupal en pratique
Headless Drupal en pratique
 
Django + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoDjango + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar Django
 
Good karma: UX Patterns and Unit Testing in Angular with Karma
Good karma: UX Patterns and Unit Testing in Angular with KarmaGood karma: UX Patterns and Unit Testing in Angular with Karma
Good karma: UX Patterns and Unit Testing in Angular with Karma
 
Heroku pop-behind-the-sense
Heroku pop-behind-the-senseHeroku pop-behind-the-sense
Heroku pop-behind-the-sense
 
Angular.js Primer in Aalto University
Angular.js Primer in Aalto UniversityAngular.js Primer in Aalto University
Angular.js Primer in Aalto University
 
Data models in Angular 1 & 2
Data models in Angular 1 & 2Data models in Angular 1 & 2
Data models in Angular 1 & 2
 

Último

Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...SelfMade bd
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxAnnaArtyushina1
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
WSO2CON2024 - Why Should You Consider Ballerina for Your Next Integration
WSO2CON2024 - Why Should You Consider Ballerina for Your Next IntegrationWSO2CON2024 - Why Should You Consider Ballerina for Your Next Integration
WSO2CON2024 - Why Should You Consider Ballerina for Your Next IntegrationWSO2
 
WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2
 
WSO2Con2024 - Software Delivery in Hybrid Environments
WSO2Con2024 - Software Delivery in Hybrid EnvironmentsWSO2Con2024 - Software Delivery in Hybrid Environments
WSO2Con2024 - Software Delivery in Hybrid EnvironmentsWSO2
 
WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...
WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...
WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...WSO2
 
WSO2CON 2024 - IoT Needs CIAM: The Importance of Centralized IAM in a Growing...
WSO2CON 2024 - IoT Needs CIAM: The Importance of Centralized IAM in a Growing...WSO2CON 2024 - IoT Needs CIAM: The Importance of Centralized IAM in a Growing...
WSO2CON 2024 - IoT Needs CIAM: The Importance of Centralized IAM in a Growing...WSO2
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2
 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2
 
WSO2CON 2024 - Designing Event-Driven Enterprises: Stories of Transformation
WSO2CON 2024 - Designing Event-Driven Enterprises: Stories of TransformationWSO2CON 2024 - Designing Event-Driven Enterprises: Stories of Transformation
WSO2CON 2024 - Designing Event-Driven Enterprises: Stories of TransformationWSO2
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2
 
WSO2Con2024 - Unleashing the Financial Potential of 13 Million People
WSO2Con2024 - Unleashing the Financial Potential of 13 Million PeopleWSO2Con2024 - Unleashing the Financial Potential of 13 Million People
WSO2Con2024 - Unleashing the Financial Potential of 13 Million PeopleWSO2
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfonteinmasabamasaba
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationJuha-Pekka Tolvanen
 
AzureNativeQumulo_HPC_Cloud_Native_Benchmarks.pdf
AzureNativeQumulo_HPC_Cloud_Native_Benchmarks.pdfAzureNativeQumulo_HPC_Cloud_Native_Benchmarks.pdf
AzureNativeQumulo_HPC_Cloud_Native_Benchmarks.pdfryanfarris8
 
WSO2Con2024 - Low-Code Integration Tooling
WSO2Con2024 - Low-Code Integration ToolingWSO2Con2024 - Low-Code Integration Tooling
WSO2Con2024 - Low-Code Integration ToolingWSO2
 

Último (20)

Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
WSO2CON2024 - Why Should You Consider Ballerina for Your Next Integration
WSO2CON2024 - Why Should You Consider Ballerina for Your Next IntegrationWSO2CON2024 - Why Should You Consider Ballerina for Your Next Integration
WSO2CON2024 - Why Should You Consider Ballerina for Your Next Integration
 
WSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaSWSO2CON 2024 Slides - Open Source to SaaS
WSO2CON 2024 Slides - Open Source to SaaS
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 
WSO2Con2024 - Software Delivery in Hybrid Environments
WSO2Con2024 - Software Delivery in Hybrid EnvironmentsWSO2Con2024 - Software Delivery in Hybrid Environments
WSO2Con2024 - Software Delivery in Hybrid Environments
 
WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...
WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...
WSO2Con2024 - Facilitating Broadband Switching Services for UK Telecoms Provi...
 
WSO2CON 2024 - IoT Needs CIAM: The Importance of Centralized IAM in a Growing...
WSO2CON 2024 - IoT Needs CIAM: The Importance of Centralized IAM in a Growing...WSO2CON 2024 - IoT Needs CIAM: The Importance of Centralized IAM in a Growing...
WSO2CON 2024 - IoT Needs CIAM: The Importance of Centralized IAM in a Growing...
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - Keynote
 
WSO2CON 2024 - Designing Event-Driven Enterprises: Stories of Transformation
WSO2CON 2024 - Designing Event-Driven Enterprises: Stories of TransformationWSO2CON 2024 - Designing Event-Driven Enterprises: Stories of Transformation
WSO2CON 2024 - Designing Event-Driven Enterprises: Stories of Transformation
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
WSO2Con2024 - Unleashing the Financial Potential of 13 Million People
WSO2Con2024 - Unleashing the Financial Potential of 13 Million PeopleWSO2Con2024 - Unleashing the Financial Potential of 13 Million People
WSO2Con2024 - Unleashing the Financial Potential of 13 Million People
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
AzureNativeQumulo_HPC_Cloud_Native_Benchmarks.pdf
AzureNativeQumulo_HPC_Cloud_Native_Benchmarks.pdfAzureNativeQumulo_HPC_Cloud_Native_Benchmarks.pdf
AzureNativeQumulo_HPC_Cloud_Native_Benchmarks.pdf
 
WSO2Con2024 - Low-Code Integration Tooling
WSO2Con2024 - Low-Code Integration ToolingWSO2Con2024 - Low-Code Integration Tooling
WSO2Con2024 - Low-Code Integration Tooling
 

How to build an AngularJS backend-ready app WITHOUT BACKEND

  • 1. ANGULARJS BACKEND STORIES How to build a backend-ready app WITHOUT BACKEND
  • 2. Wearing multiple hats at Narada Robotics startup, from coding to whatever else… Main interests - mobile development IN LOVE WITH ANGULARJS Enrique Oriol CTO @ Narada Robotics blog.enriqueoriol.com @enrique.oriol
  • 3. SCENARIO I want you to develop my frontend I’ll provide you with an API REST
  • 4. SCENARIO I want you to develop my frontend I’ll provide you with an API REST
  • 5. BACKEND STORIES 5 URLS TO LOCAL JSONS Of course we can use urls to local JSON files, but… We cannot use POST, PUT... We cannot use response codes We cannot access headers So we cannot really prepare client side API connections @enrique.oriol
  • 7. MOCKING THE SERVER What we will cover: URL DEFINITIONS01 CREATING JSON FIXTURES02 USING $HTTPBACKEND03 USING $RESOURCE04 DYNAMIC RESPONSES05 BACKEND PERSISTENCE06
  • 8. BACKEND STORIES 8 CAUTION This is NOT intended to be used in PRODUCTION @enrique.oriol
  • 9. BACKEND STORIES 9 Why not Node.js mock? It is just an alternative to any other mock server It runs at the same JS VM, so it does not need a public endpoint somewhere Think about sending the results to a client in the case of a hybrid app @enrique.oriol
  • 10. BACKEND STORIES 10 You can download code here: https://github.com/kaikcreator/UserRanking And play with the results here: http://kaikcreator.github.io/UserRanking/ EXAMPLE APP We will use User Ranking app as example @enrique.oriol
  • 11. QUICK OVERVIEW USER RANKING Require Following Integration With API NON AUTHENTICATED CREATE USER - POST user endpoint USERS RANKING - GET users endpoint AUTHENTICATED UPDATE USER - PUT user endpoint
  • 13. BACKEND STORIES 13 URL DEFINITION app/services/url/URLModule.js angular.module('userRanking.urlsModule', []) .constant('urlConst', (function(){ var protocol = 'http://'; var domain = 'www.userRanking.com'; var base = '/api'; var version = '/v1'; var placeholders = { userId: '[userId]' } return { user: protocol + domain + base + version + '/user/' + placeholders.userId, users: protocol + domain + base + version + '/users', placeholders: placeholders }; })()) @enrique.oriol
  • 14. BACKEND STORIES 14 URL DEFINITION app/services/url/URLModule.js .factory('urls', ['urlConst', function(urlConst){ var urls = angular.copy(urlConst); var replacePlaceholders = function(url, placeholders){ for(var key in placeholders){ url = url.replace(urlConst.placeholders[key], placeholders[key]); } return url; }; //generate dinamic urls here urls.user = function(id){ return replacePlaceholders(urlConst.user, {userId: id}); }; return urls; }]); @enrique.oriol
  • 15. BACKEND STORIES 15 URL DEFINITION This Approach EASY TO EXTEND WITH MORE ENDPOINTS ISOLATES URL DETAILS FROM OTHER SERVICES @enrique.oriol
  • 16. CREATING JSON FIXTURES We should agree in the models
  • 17. BACKEND STORIES 17 CREATING JSON FIXTURES How a user will look like { id: userId, name: username, image: urlToUserImage, rating: userRating } @enrique.oriol
  • 18. BACKEND STORIES 18 CREATING JSON FIXTURES app/fixtures/users.json [ { "id": "1", "name": "Peter", "image": "user1.png", "points": 150 }, . . . { "id": "6", "name": "Travis", "image": "user6.png", "points": 100 } ] @enrique.oriol
  • 19. E2E $HttpBackend As a mechanism not to test, but to mock our server
  • 20. BACKEND STORIES 20 e2e $httpBackend https://docs.angularjs.org/api/ngMockE2E/service/$httpBackend 1. download Installation $ bower install angular-mocks 2. include source <!-- mock server --> <script src="bower_components/angular-mocks/angular-mocks.js"></script> 3. include module angular.module('app', ['ngMockE2E']); @enrique.oriol
  • 21. BACKEND STORIES 21 e2e $httpBackend https://docs.angularjs.org/api/ngMockE2E/service/$httpBackend When URL: return object with responds & passthrough methods Basics when( method, url, [data], [headers], [keys] ); Responds Passthrough $httpBackend.when(‘GET’, url).respond({} / []) $httpBackend.when(‘GET’, url).respond(function(method, url, data, headers, params){}) $httpBackend.when(‘GET’, url).passThrough() @enrique.oriol
  • 22. BACKEND STORIES 22 e2e $httpBackend app/services/mock/MockServerModule.js angular.module('userRanking.mockServerModule', ['ngMockE2E', 'userRanking.urlsModule']) .run(['$httpBackend', 'urls', function($httpBackend, urls){ /*mocked data*/ $httpBackend.whenGET(urls.users) .respond([ { "id":"5", "name":"Alex", "image":"user5.png", "points": 210}, { "id":"6", "name":"Travis", "image":"user6.png", "points": 100} ]); }]) @enrique.oriol
  • 23. $resource As a mechanism to load local JSON files
  • 24. BACKEND STORIES 24 $resource https://docs.angularjs.org/api/ngResource/service/$resource 1. download Installation $ bower install angular-resource 2. include source <!-- mock server --> <script src="bower_components/angular-resource/angular-resource.js"></script> 3. include module angular.module('app', ['ngResource']); @enrique.oriol
  • 25. BACKEND STORIES 25 $resource: return object with different methods, that populates async Usage $resource(url, [paramDefaults], [actions], options) Returned object methods $resource https://docs.angularjs.org/api/ngResource/service/$resource { 'get': {method:'GET'}, 'save': {method:'POST'}, 'query': {method:'GET', isArray:true}, 'remove': {method:'DELETE'}, 'delete': {method:'DELETE'} }; @enrique.oriol
  • 26. BACKEND STORIES 26 $resource app/services/mock/MockServerModule.js angular.module('userRanking.mockServerModule', ['ngMockE2E','ngResource', 'userRanking.urlsModule']) .constant('fixturePaths', { "users": "fixtures/users.json" }) .run(['$httpBackend', 'urls', 'fixturePaths', '$resource', function($httpBackend, urls, fixturePaths, $resource){ /* allow local calls */ $httpBackend.whenGET(/fixtures/.*/).passThrough(); /*mocked data*/ $httpBackend.whenGET(urls.users).respond( $resource(fixturePaths.users).query() ); }]) @enrique.oriol
  • 27. BACKEND STORIES 27 If you perform a $http call just after app boostrap, it’s possible that $resource is not already populated, returning an empty value. In that case you should perform some additional trick, always trying to perform all the stuff in MockServerModule, so it’s easier to “shut down” mock server when real server comes to life. You can see a decorator approach in the example code available on github. REMEMBER that $resource is populated ASYNC $resource @enrique.oriol
  • 28. Dynamic responses The power behind mocking server with E2E $httpBackend
  • 29. BACKEND STORIES 29 Dynamic responses Using function inside $httpBackend.respond <!-- mocked data --> $httpBackend.whenGET(urls.users).respond( $resource(fixturePaths.users).query() ); /*mocked data*/ var usersResource = $resource(fixturePaths.users).query(); $httpBackend.whenGET(urls.users).respond(function(method, url, data, headers){ return [200, usersResource, {}]; }); Changing this: Into this: Gives us access to url, data and headers, so our response can be dynamic @enrique.oriol
  • 30. BACKEND STORIES 30 Dynamic responses We can perform data validation, and return custom headers .run(['$httpBackend', 'urls', 'fixturePaths', '$resource', function($httpBackend, urls, fixturePaths, $resource){ /*...previous stuff...*/ /* regex allowing any user id in user url*/ var anyUserUrl = new RegExp(urls.user('.*')); /*mock POST rx of a new user, and return auth token*/ $httpBackend.whenPOST(anyUserUrl).respond(function(method, url, data, headers){ data = angular.fromJson(data); if(data.name === undefined || !angular.isString(data.name) || data.name.length === 0){ return [400, null, null]; } else{ var user = { "id": "7", "name": data.name, "points": 0 }; return [200, user, {Authorization: "1234567890asdfghjklzxcvbnm"}]; } }); }]) @enrique.oriol
  • 31. BACKEND STORIES 31 Dynamic responses We lack persistence .run(['$httpBackend', 'urls', 'fixturePaths', '$resource', function($httpBackend, urls, fixturePaths, $resource){ /*...previous stuff...*/ /*mock POST rx of a new user, and return auth token*/ $httpBackend.whenPUT(anyUserUrl).respond( function(method, url, data, headers){ data = angular.fromJson(data); if(headers['Authorization'] !== "Token 1234567890asdfghjklzxcvbnm"){ return [401, null, null]; } else if(data.name === undefined && data.points === undefined && data.image ===undefined){ return [400, null, null]; } else{ /*here we need to return updated data, so our app can reflect changes*/ var user = {...}; return [200, user, {}]; } }); }]) @enrique.oriol
  • 32. Backend persistence Completing the experience with localStorage
  • 33. BACKEND STORIES 33 Write in LS $window.localStorage['myKey'] = angular.toJson(myData); Read from LS var data = angular.fromJson($window.localStorage['myKey']); Usage Backend persistence Local Storage @enrique.oriol
  • 34. BACKEND STORIES 34 .constant('lsMock', { "users": "ls-cached-users" }) .factory('mockedUsers', ['$window', '$resource', 'fixturePaths', 'lsMock', function($window, $resource, fixturePaths, lsMock){ var service = {}; service.list = angular.fromJson($window.localStorage[lsMock.users]); if(!service.list || service.list.length === 0){ service.list = $resource(fixturePaths.users).query(); } service.save = function(){ $window.localStorage[lsMock.users] = angular.toJson(service.list); }; service.add = function(user){ service.list.push(user); service.save(); }; Backend persistence Define a service to handle with cached users service.update = function(user){ for(var i=0; i<service.list.length; i++){ if(service.list[i].id == user.id){ service.list[i].points = user.points; service.save(); return; } } }; service.getById = function(userId){ for(var i=0; i<service.list.length; i++){ if(service.list[i].id == userId){ return service.list[i]; } } return null; }; return service; }]) @enrique.oriol
  • 35. BACKEND STORIES 35 .run(['$httpBackend', '$resource', 'urls', 'mockedUsers', function($httpBackend, $resource, urls, mockedUsers){ /* local calls */ $httpBackend.whenGET(/fixtures/.*/).passThrough(); /* regex allowing any user id in user url*/ var anyUserUrl = new RegExp(urls.user('.*')); /*mocked users list*/ $httpBackend.whenGET(urls.users).respond(function(method, url, data, headers){ return [200, mockedUsers.list]; }); Backend persistence Using our service in mock server - whenGET @enrique.oriol
  • 36. BACKEND STORIES 36 /* mock update user*/ $httpBackend.whenPUT(anyUserUrl).respond( function(method, url, data, headers){ data = angular.fromJson(data); var userId = url.replace(urls.user(''), ''); if(!data.id) {data.id = userId;} if(headers['Authorization'] !== "Token 1234567890asdfghjklzxcvbnm"){ return [401, null, null]; } else if(data.name === undefined && data.points === undefined && data.image ===undefined){ return [400, null, null]; } else{ mockedUsers.update(data); data = mockedUsers.getById(userId); return [200, data, {}]; } }); Backend persistence Using our service in mock server - - whenPUT @enrique.oriol
  • 37. BACKEND STORIES 37 /* mock new user*/ $httpBackend.whenPOST(anyUserUrl).respond( function(method, url, data, headers){ data = angular.fromJson(data); if(data.name === undefined || !angular.isString(data.name) || data.name.length === 0){ return [400, null, null]; } else{ var user = { "id": ''+ mockedUsers.list.length, "name": data.name, "points": 0 }; mockedUsers.add(user); return [200, user, {Authorization: "1234567890asdfghjklzxcvbnm"}]; } }); }]) Backend persistence Using our service in mock server - - whenPOST @enrique.oriol
  • 38. You’re ready Time to play with code http://kaikcreator.github.io/UserRanking/