本文转自:https://malcoded.com/posts/angular-backend-express

Angular is a single page application framework. Unfortunately, that does not mean that you don't require a server for certain tasks.

After all, your data has to be served from somewhere...

But don't worry, setting up a server is easier than you might think. In fact, the first server we will create does only consist of three lines of code! For that, we will be using Node.js that allows us to use JavaScript to write our server-applications. We will also use the Express framework to create your first REST-API in just a few, simple steps.

In this tutorial, we will take a look at creating server-applications with Node.js and the Express framework in relation to angular. We will not only create our first small server-application, but also create a functional REST-API to serve our data.

Afterward, we take a close look, how we can utilize our new API, to request and send data from any angular application.

Now you might ask yourself: "What the .... is a REST-API?"

Don't worry, we will come to that, as well!

Ready?

Let's get started!

REST is not what you are looking for? 
Try GraphQL with Angular Apollo & Express instead!

Not a fan of Node.js backends?
Then this guide to building a REST-API with ASP.Core is for you!

Setting up a new Express Project

As angular developers, we are used to generating our project structure with the angular-cli. Unfortunately, there is no such thing as a node-cli. That means we have to create our project files by hand. Can you believe that?

Well, it is not that bad as it sounds. To create our first functional node.js server application, we only have to create one file.

That file is a simple JavaScript file. It is the entry point for our server application. These files are typically called index.js or server.js.

I like server.js, so let's go ahead and create that file in a new directory of your choice.

Done! Not that hard, was it?

Setting up the node.js Environment

To run a node.js application, we have to install node.js on our machine first. You can download it at theofficial node.js website. For this tutorial, it does not matter, which version you choose. If you want to be on the save side, choose the long-term-support version (LTS).

Download the setup-executable and follow the instructions to install node.js on your computer. At one point, the wizard will ask if you want to install npm, as well. Make sure you do so. On Windows machines, you may need to restart your computer afterward.

Now that we have everything installed, we can initialize a new npm-project. What this will do for us, is generate a new package.json file and fill in its basic structure. As an angular developer, you should be familiar with this file already. It is also included in your angular projects. It keeps track of all dependencies of your application.

Let's generate the package.json file, by opening a command line interface in your server-application's directory. Use the command

npm init

and answer the questions, the tool is asking you. It does not matter what you type in. It will have no effect on your application itself. It is just meta-data.

Creating our first Node.js Server-Application

In this tutorial, we are going to create a server using the Express framework. While it is certainly possible, to create a server application without any frameworks, it makes development much easier.

So, the first line of our application looks like this:

 
server.js
const express = require('express');

In this piece of code, we first create a constant called "express" that we will later use to set up the express framework.

What does require do?

Express is an external dependency. By using "require" we tell node.js that it has to be pulled into our code because we need it.

In angular, we are doing just the same very often. The only difference here is, that we use a little bit different syntax.

Because we are using Typescript in angular, we are used to import statements. In fact, these import statements are compiled to the require statements when the TypeScript is compiled to JavaScript.

The above line would look this in TypeScript:

 
TypeScript equivalent
import * as express from 'express'

Looks more familiar, doesn't it?

Installing External Dependencies

Just like in angular, external dependencies have to be pulled and installed, before they can be used. Installed dependencies are located in a directory called "node_modules" inside of the root directory.

To install external dependencies, we are using package-managers like npm.

Use the following command to install express using npm:

npm install express --save

This command should have created the "node_modules" folder inside of your project directory.

Initializing the Express Framework

To initialize the express framework, we need to call the constant express function we just required. It will return an Express-Object. This Express-Object is essential and used to set up the application itself, add routes and rest-endpoints initialize middleware.

Doing so looks like this:

 
server.js
const app = express();

Again, nothing fancy, right?

Starting our Server

Now that we have initialized the framework, we can fire up our server. This is done by calling the "listen"-method of our Express-Object. This method tells the server to listen for incoming requests on the given port.

 
server.js
app.listen(8000, () => {
console.log('Server started!');
});

In this case, we tell it to listen on port 8000. We also pass in a callback-function, that is called, once the server has successfully started. Inside there we log our successful start to the console.

Running our Server with Node.js

To run our script, we need to tell node.js to execute it. This can be done, using the node command in your command line interface.

Open a new command line interface in your project root directory and start your server by typing:

node server.js

Alternatively, you can also use

npm start

because npm has created a script inside of our package.json that is internally calling the node command.

If you are using Visual Studio Code, you can also start your server by hitting F5. This also automatically attaches the debugger to the process, which is quite useful.

"REST-API"? Can you eat that?

As I told you already, we are going to create a REST-API. But what is that exactly? Let's find out!

I will try to keep this short: REST is a standardized way of building http-endpoints.

It uses standard HTTP-verbs like get, post, put & delete to express read, create update & delete (CRUD) operations.

All these methods (verbs) are applied to one endpoint, which represents the object to be modified. This has an object-oriented touch to it,

For example, if I wanted to modify a cat in any way, the endpoint would be named "cats" or "cat", depending on who you ask. I prefer the plural form fro myself.

Here is how the CRUD operations are modeled.

CRUD Operations

Create: To create a new object under an endpoint, a post-request is sent to the REST-Endpoint containing the new object to create in the post-body.

Read: To read all objects from an endpoint, e.g if you want to know about all cats, a get-request is sent to the "cats" endpoint. If you are interested in one specific cat, you append the id/name of the cat to the route "cats/cat1".

Update: To update an object, a put request is sent to the endpoint. The identifier is added to the route e.g. "cat/cat1". The information of the object is added to the put-body.

Delete: To delete an object, a delete request is sent to the endpoint with the identifier of the wanted object added to the route.

These crud-operations can be directly mapped to the database, for example mongodb, if you are using the MEAN-stack.

Our first REST-Endpoint

Enough theory for now, let's dive right into the code. For our example, we are going to create a cat-endpoint, possibly serving a database of all cats in the world. Yes, all of them!

Getting all Objects from an Endpoint

As discussed before, we get a list of all objects of an endpoint, by sending a get request to that endpoint directly.

Now, we have to tell our server, what to do, if it receives a request at that endpoint.

To do so, we are defining a so-called route, which is the "path" to the endpoint. In this example, the base path to our REST-API will be "api". This enables us to serve other things next to the REST-API. For example, we could serve our angular application under the "app" route.

To define a route, we call the route-method on our express object. 
Next, we wall the get-method on that route, to tell express that we want to register a callback for the HTTP-get request at that specific route.

 
server.js
app.route('/api/cats').get((req, res) => {
});

Inside of this callback method, we can decide, what should happen, when a user requests that route. For that, we get two objects. The request-object and the response-object.

The request-object does contain details about the request of the user. With this object, we get access to all the data of the request, for example, the headers or the body.

The response-object on the other hand helps us to send a response back. It does not only contain all the information of the response but also convenient methods, we can use to shape our response.

In our example, we are going to use the send-method, to send back any JavaScript object as JSON in the response body.

 
server.js
app.route('/api/cats').get((req, res) => {
res.send({
cats: [{ name: 'lilly' }, { name: 'lucy' }]
});
});

Getting one specific Object from an Endpoint

The second method of a REST-endpoint, is getting one specific element from the API. By convention, the identifier of that object is appended to the route.

For example, if we want to get everything about the cat called "lucy", we would call the following route:

api/cats/lucy

But now we got a problem. The last of the element of the route is completely dynamic, as it could be any cat's name. So how do we tell express that we want to handle that route?

For that, express has a concept called route parameter and it works surprisingly similar to angular route parameters. We declare a parameter by using a colon.

The code to set this route up looks like this:

 
server.js
app.route('/api/cats/:name').get((req, res) => {});

The ":name" tells express, that we expect a dynamic string as input. We can get the value of this route-parameter by getting the params-object from the request object. We query it using the name of our route-parameter ("name").

 
server.js
app.route('/api/cats/:name').get((req, res) => {
const requestedCatName = req.params['name']
});

All we have to do now is to return the cat with that name. In a real-world application, we would now search our database for that cat. But for demonstration purposes, we just return a new cat-object with the requested name.

 
server.js
app.route('/api/cats/:name').get((req, res) => {
const requestedCatName = req.params['name'];
res.send({ name: requestedCatName });
});

Sending a new Object to an Endpoint

Another method of a REST-API is creating a new object at the endpoint. This method is different to the methods we looked at before because it is using the HTTP-post-request instead of the get-request.

This REST-method is used to send new objects to the server. For example, if we would want to insert a new cat into our (not existing) cat-database, we would use this method for that.

To get access to the post-body of the request, we need to add a little tool called body-parser. This parses the body of the requests and adds it as a new property to the request object.
We need the body of the post request, because it contains the information about the new cat we are about to create.

Just add the body-parser to the dependencies of our server by using this command:

npm install body-parser --save

We then require it and tell express to use it for every request (more on that later).

 
server.js
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.route('/api/cats').post((req, res) => {
res.send(201, req.body);
});

You may have noticed that something else looks different here. We are using the "send"-method with two parameters instead of one. Now, the first parameter is the HTTP-status-code and the second one our payload. Normally, the "send"-method uses the status code "200" - OK. Because the request "created" something, a new cat entry in our database, for example, the status code "201" - Created is a much better fit.

Changing an Object at an Endpoint

Inserting new Objects might not cover all of your needs. Depending on your use-case, you probably want to modify existing objects. We can create a route that allows for that using the express-put-method.

 
server.js
app.route('/api/cats/:name').put((req, res) => {
res.send(200, req.body);
});

Deleting an Object at an Endpoint

Creating a delete method is quite simple. All we have to do is the delete-method from express. Again, we are using a route-parameter, to determine which cat to delete from the database.

 
server.js
app.route('/api/cats/:name').delete((req, res) => {
res.sendStatus(204);
});

The status-code "204" -No Content, means that we are not sending back any payload, but the request was successful.

Plug & Play Functionality using Express-Middleware

That's almost it. We have successfully created a REST-API!

Before we continue, by building the corresponding angular application, we should take a short look at middleware in express, because it is such an important concept of the framework.

It will also help as to prevent a very common mistake.

So what is Middleware?

Middleware is a very broad and abstract concept. Basically, it is software, that is placed between two other components. Well, I told you it is abstract...

What does that mean for our application?

Everything in express is middleware. There is some component that takes the incoming requests and there is something that spits out the responses. Everything in between is handled by middleware.

Middleware in Express

Our routes with their callbacks, for example, are a kind of middleware. We get a request and help to shape a response from that.

It turns out, the body-parser we used already, is middleware as well. It intercepts every request and looks for their bodies. It then modifies the request object to contain that body information.

Middleware in express builds a kind of chain. The request is passed from the first registered middleware to the last one. Once there is no one left that wants to intercept the request, the response is sent back.

Enabling CORS

The first thing I realize, when I want to test my brand new API with my angular app, is, that I forgot to enable CORS.

CORS or cross-origin-resource sharing is the process of making an HTTP-request to a top-level domain that is different to the domain, the browser is currently at. For example, if I would make a request from this page to google.com, it would be a cross-origin-request.

This same-origin-policy prevents us from making HTTP-requests from our JavaScript code to APIs, that don't want to be called from a different origin. And that makes absolute sense. I don't want my API to be used by other sites, possibly doing malicious things with the gathered data.

When it comes to single-page-applications (like angular) though, almost every HTTP-request is made from JavaScript (AJAX). Furthermore is not to uncommon, that the API is not hosted under the same domain as the angular app.

We then have to enable CORS. But it is not just an on/off feature. We can enable COR only from certain domains.

We can do so with express by using the CORS middleware.

npm install cors --save
const cors = require('cors')
var corsOptions = {
  origin: 'http://example.com',
  optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204 
}
app.use(cors(corsOptions))

This middleware will now intercept every request and add the corresponding cors headers to the response.

Consuming our Express-API in an Angular Application

Now I will show you real quick, how to integrate your API into your angular application.
For that, I assume that you know how to set up a basic application using the angular-cli. Some basic understanding could help, as well.

If you feel like you are lacking knowledge in one or both of the mentioned things, I recommend you read my Angular Beginners Guidefirst.

So first we create a basic angular-cli application. Of course, you can do this with any existing application, as well. All we are going to do here is to create an angular service, that consumes our new REST-API.

For that, we are using the angular HttpClient. So you need to import the HttpClientModule into a moduleof your choice, but typically the App-Module.

Next, create a new service. I will call that one "CatService".

Here is what this service looks like:

 
cat.service.ts
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { HttpClient } from '@angular/common/http';
export interface Cat {
name: string;
}
@Injectable()
export class CatService {
constructor(private http: HttpClient) {}
getAllCats(): Observable<Cat[]> {
return this.http.get<Cat[]>('http://localhost:8000/api/cats');
}
getCat(name: string): Observable<Cat> {
return this.http.get<Cat>('http://localhost:8000/api/cats/' + name);
}
insertCat(cat: Cat): Observable<Cat> {
return this.http.post<Cat>('http://localhost:8000/api/cats/', cat);
}
updateCat(cat: Cat): Observable<void> {
return this.http.put<void>('http://localhost:8000/api/cats/' + cat.name, cat);
}
deleteCat(name: string) {
return this.http.delete('http://localhost:8000/api/cats/' + name);
}
}

Conclusion

In this tutorial, we learned how to set up a node.js server-application from scratch and created a very basic but functional REST-API using the express framework.

I hope you enjoyed this post.

If you did please hit the share buttons below and help other people building their APIs, as well.

Have a fantastic day!

[转]Building a REST-Backend for Angular with Node.js & Express的更多相关文章

  1. Practical Node.js (2018版) 第8章:Building Node.js REST API Servers

    Building Node.js REST API Servers with Express.js and Hapi Modern-day web developers use an architec ...

  2. 深入理解jQuery、Angular、node中的Promise

    最初遇到Promise是在jQuery中,在jQuery1.5版本中引入了Deferred Object,这个异步队列模块用于实现异步任务和回调函数的解耦.为ajax模块.队列模块.ready事件提供 ...

  3. socket.io+angular.js+express.js做个聊天应用(四)

    接着上一篇 使用angularjs构建聊天室的client <!doctype html> <html ng-app="justChatting"> < ...

  4. soket.io.js + angular.js + express.js(node.js)

    soket.io.js + angular.js + express.js(node.js) 今天搭建个soket.io.js + angular.js + express.js的环境, 采坑无数,特 ...

  5. Angular和Vue.js 深度对比

    Vue.js 是开源的 JavaScript 框架,能够帮助开发者构建出美观的 Web 界面.当和其它网络工具配合使用时,Vue.js 的优秀功能会得到大大加强.如今,已有许多开发人员开始使用 Vue ...

  6. EmberJS 为什么我偏爱 Ember.js 胜过 Angular 和 React.js

    文章写的很老到,非常值得一看!评论也很精彩,值得一看 为什么我偏爱 Ember.js 胜过 Angular 和 React.js 前几天看到了这篇文章:Why I prefer Ember.js ov ...

  7. Angular、React.js 和Node.js到底选谁?

    为了工作,程序员选择正确的框架和库来构建应用程序是至关重要的,这也就是为什么Angular和React之间有着太多的争议.Node.js的出现,让这场战争变得更加复杂,虽然有选择权通常是一件很棒的事情 ...

  8. socket.io+angular.js+express.js做个聊天应用(三)

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/www19940501a/article/details/27590611 接着前面博客文章socke ...

  9. Angular build Error:In this configuration Angular requires Zone.js

    Angular cli 运行 build后打开生成的index.html报错:In this configuration Angular requires Zone.js 生成代码如下: ng bui ...

随机推荐

  1. SQL SERVER 小语法

    1. 取字段长度:len select * from 表名 where len(expmessage)=1 2.rtrim, ltrim rtrim(ObjectName)

  2. Tomcat架构解析(五)-----Tomcat的类加载机制

    类加载器就是根据类的全限定名(例如com.ty.xxx.xxx)来获取此类的二进制字节流的代码模块,从而程序可以自己去获取到相关的类. 一.java中的类加载器   1.类加载器类别 java中的类加 ...

  3. java内存模型和垃圾回收(收藏)

    java内存模型: https://www.cnblogs.com/handsomeye/p/5442879.html java垃圾回收 http://www.cnblogs.com/handsome ...

  4. Chrome书签添加到百度网盘

    一:Chrome是最干净的浏览器了,但是无奈国内的环境导致书签不方便保存到云端,如果保存到本地那么就要经常自己备份之类的: 二:由以上的需求背景终于找到了可以将chrome打开的网页保存到百度网盘里[ ...

  5. Paper | 帧间相关性 + 压缩视频质量增强(MFQE)

    目录 1. ABSTRACT 2. INTRODUCTION 3. RELATED WORKS 3.1. Quality Enhancement 3.2. Multi-frame Super-reso ...

  6. 用jstack自动化捕抓异常java代码脚本

    #!/bin/bashdate=` date +%y%m%d-%H%M`pid=`top -bn1 |grep java | awk '{print $1 "\t" $9}' |h ...

  7. 内置函数_range()

    range() range()语法格式为 range([start,] stop [,step])# 有三种用法range(stop)range(start,stop)range(start,stop ...

  8. Python自动化开发 - MySQL(一)

    本节内容 一.概述 二.下载安装 三.数据库操作 四.数据表操作 五.表内容操作 一.概述 1.什么是数据库 ? 答:数据的仓库,如:在ATM的示例中我们创建了一个 db 目录,称其为数据库 2.什么 ...

  9. TortoiseSVN与TortoiseGit

    TortoiseSVN与TortoiseGit 功能:版本控制+备份处理 差异:SVN二段式,没有中间存储点,直接提交后到达了远程存储点:要想对本地的修改进行记录,必须要与SVN服务器进行通讯,无法只 ...

  10. git & github 同步文件

    step1 : 在github上建立一个 repository https://github.com/ntu-juking/softwaretesting.git repository name is ...