theme | class | highlighter | lineNumbers | info | background |
---|---|---|---|---|---|
seriph |
text-center |
shiki |
true |
Getting data from the Internet
|
Getting data from the Internet
The missing part of our codes.
Consider the vue
code.
The posts
is a fixed array, which is useless in most of real world projects.
We have tried localStorage
API to storage/get data in our browser.
But what if we want users access data everywhere?
<template>
<ul>
<li v-for="post in posts">
{{ post.title }}
</li>
</ul>
</template>
<script>
export default {
data() {
return {
posts: [
{ title: 'Post #1' },
{ title: 'Post #2' },
{ title: 'Post #3' },
]
}
}
}
</script>
Where is our data?
For a real-world blog, the data(posts) is not stored in frontend(the browser), it is stored in server.
Precisely speaking, the data is stored in a Database in server.
To showing content of a post, a blog can:
- Generate a HTML file for each post, but it costs too much and hard to maintain
- Use a template, and generate full HTML file ONLY when user requests. A template looks like following (written in Jinja):
<h1>{% post.title %}</h1>
<main>
{% post.content %}
</main>
Getting data from server with Javscript
The basic transfer protocol in the Internet
A HTTP request looks like this:
GET /count.js HTTP/1.1
Host: realpython.disqus.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://realpython.com/
Connection: keep-alive
GET
specifies HTTP method/count.js
specifies a request targetHTTP/1.1
specifies the procotol version
Then we can show data in our webpace via Javascript
.
Suppose there is an API for getting post info.
GET /posts?id=1 HTTP/1.1
Host: api.nimo.network
...
app.get('/posts', (request, response) => {
const post = Posts[request.query.id]
response.send(post) // in json format
})
Via fetch
API or axios
library
Following is an example that getting data from website above
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => console.log(json))
The fetch
function returns a Promise.
A Promise can be thought as something representing a running task.
The .then
function of a Promise receive a function,
these functions will run after the task is finished.
And the result of the running task will be passed to the function as an argument.
Create a button, show todos from https://jsonplaceholder.typicode.com/todos/
<template>
<div>
<button @click="getData">Get Data</button>
<ul>
<li v-for="todo in todos">
</ul>
</div>
</template>
<script>
export default {
data() { return { todos: [] } },
methods: {
getData() {
fetch('https://jsonplaceholder.typicode.com/todos')
.then(response => response.json())
.then(json => this.todos = json)
}
}
}
</script>
How to send message to server
From the previous example we know how to get data from server, but how do we send data to server?
Of course we can pass our data in query string like /register?username=nimo&password=nb
But this is not cool because:
- The URL(Uniform Resource Locator) has limitation in length (depends on browser)
- It does not support file upload
- It is sometimes confuse when using
/todos?title=todoTitle
to create todo
We can use POST
, PUT
, PATCH
instead
- Create
- Read
- Update
- Delete
Suppose we have a resource called todo
, what we usually do is:
- Create a todo
- Read todos or read a specific todo
- Update a todo (title/description/...)
- Delete a todo
But some of them are terrible...
Method | URL | Description |
---|---|---|
GET | /allTodos |
get all todos |
GET | /todo |
get all todos |
GET | /todo?id=1 |
get a todo that id equals 1 |
POST | /createTodo |
create a todo |
POST | /updateTodo |
update a todo |
REpresentational State Transfer API, a Better API Design Pattern
The RESTful style uses HTTP method and URL to determine what to do.
Suppose we have a resource called todo
, the RESTful API looks like:
Method | URL | Description |
---|---|---|
GET | /todos |
get all todos |
GET | /todos?done=false |
get undone todo |
GET | /todos/100 |
get a todo that id equals 100 |
POST | /todos |
create a todo |
PUT/PATCH | /todos/100 |
update Todo #100 |
DELETE | /todos/100 |
delete Todo #100 |
More about this style
Suppose we have another resource called user
, each user
can have many todo
s.
The API looks like:
Method | URL | Description |
---|---|---|
GET | /users |
get all users |
GET | /users/100 |
get a todo that id is 100 |
GET | /users/100/todos |
get all todos that belongs to user #100 |
GET | /users/100/todos/10 |
(try to) get todo #10 that belongs to user #100 |
layout: image-right image: https://source.unsplash.com/collection/94734566/960x1080
Why this style?
- Uniform Interface
- Self-descriptive
- Hard to support complex scenario
Via fetch
API
https://developer.mozilla.org/en-US/docs/Web/API/Fetch\_API/Using\_Fetch
function request(url, method='GET', data={}) {
return fetch(url, {
method: method,
mode: 'cors',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data),
})
}
request('https://jsonplaceholder.typicode.com/todos/')
.then(response => response.json())
.then(json => console.log(json))
request('https://nimo.network/request', 'POST', { guess: 123 })
.then(response => response.json())
.then(json => console.log(json))
Via axios
library
npm install axios
Add the following lines to your .vue
file if you are using vite+vue
import axios
axios.post('/api', {
guess: 123
}).then(response => console.log(response))
- Download/Clone the code from https://github.com/truc0/silly-guess/
cd
to that directory- Run the following command:
npm install
- Run the following command:
npm run start
- Visit
https://localhost:8000
to see what happend
- Send a POST request to the server (
https://localhost:8000
). - Remember the token in response, it is the id of new created game
- The new game is already generated, the answer is a integer between 0 (included) and 100 (excluded)
- Send a POST request to the server (
https://localhost:8000/<token>
), replace the<token>
with your new game id - The response should shows guessing state (
too large
,too small
orbingo
)
- Send a GET request to (
https://localhost:8000/<token>
), replace the<token>
with your new game id - The response should shows the state of the game (guess count, state)
- This program is not fully RESTful
- Take a look at
README.md
andindex.js
to know how this works
layout: cover background: 'https://source.unsplash.com/random/1080x720'
Have a good time with Frontend Development!