Web 使用fetch请求后端服务

综合技术 2017-11-15

上篇我们使用了ssm构建了我们简历的服务, 这篇我们从前端的视角进行网络请求, 对于react就要讲讲fetch这个库的使用, 对于vue就要讲讲axios这个库, 对于axios之前已经讲过, 这篇就来讲讲fetch的使用.

参考链接:

以下内容在上述文章基础上进行, 请事先查阅.

安装fetch

当然说到fetch, 其实就是对于ajax的一个封装, 类似于iOS的AFNetworking, 首先我们先从npm 加载这个库.

$ npm instaill fetch --save

在开始进行网络请求之前, 我们需要和后端定义好接口以及返回的数据, 当然如果是前后端一起开发的话, 就没有这个困扰了.

查阅fetch文档

文档链接

Usage synopsis (use the argument links to find out more):

fetch(url, options).then(function(response) {
  // handle HTTP response
}, function(error) {
  // handle network error
})
More comprehensive usage example:

fetch(url, {
  method: "POST",
  body: JSON.stringify(data),
  headers: {
    "Content-Type": "application/json"
  },
  credentials: "same-origin"
}).then(function(response) {
  response.status     //=> number 100–599
  response.statusText //=> String
  response.headers    //=> Headers
  response.url        //=> String

  return response.text()
}, function(error) {
  error.message //=> String
})

自行封装fetch

像我们在iOS中使用第三方库的时候回在其基础上封装一层, 以便日后维护方便, 对于前端, 设计思想也是一样的, 我们就来新建一个http.js来封装网络请求和接口.

const host = 'http://localhost:8080';

export function GET(url) {
    var fetchOptions = {
        method: 'GET'
    };
    return new Promise((resolve, reject) => {
        fetch(url, fetchOptions).then(response => response.json()).then(response => resolve(response.data)).catch((error) => {
            reject(error);
        })
    });
}

export const URL = {
    fetchProfile: `${host}/portal/fetch_profile.do`,
    fetchProjects: `${host}/portal/fetch_projects.do`,
    fetchGitHub: `${host}/portal/fetch_github.do`,
    fetchArticles: `${host}/portal/fetch_articles.do`,
    fetchExperience: `${host}/portal/fetch_experience.do`,
    fetchContact: `${host}/portal/fetch_contact.do`
}

非常简单的在fetch的基础上使用Promise进行封装, 并将所需要的接口整合到一起以便日后的维护.

查看接口

为例完成下图的展示, 我们已经通过ssm写好了这个接口.

我们就以第一个接口举例 fetchProfile:
${host}/portal/fetch_profile.do`,如果你对es6模板字符串的语法不熟悉的话, 可以自行搜索下, 我们先来看看这个接口的返回.

/* http://localhost:8080/portal/fetch_profile.do */
{
    "status": 0,
    "data": {
        "profileImage": "http://upload-images.jianshu.io/upload_images/1229762-23e162b9bd6b9c39.JPG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240",
        "profileName": "Shuangquan Zhu",
        "profileCareer": "Designer / Developer",
        "profileLocation": "Shanghai",
        "profileSocialList": [
            {
                "src": "http://upload-images.jianshu.io/upload_images/1229762-877e3e5c2260bcf1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240",
                "href": "https://github.com/coderzsq"
            },
            {
                "src": "http://upload-images.jianshu.io/upload_images/1229762-f6525252f3e8387b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240",
                "href": "http://www.jianshu.com/u/9d7fad1a4693"
            },
            {
                "src": "http://upload-images.jianshu.io/upload_images/1229762-a69614a97de93f36.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240",
                "href": "http://upload-images.jianshu.io/upload_images/1229762-453920a3f4eedcd8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"
            },
            {
                "src": "http://upload-images.jianshu.io/upload_images/1229762-91b0949aec719aab.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240",
                "href": "http://coderzsq.github.io/"
            }
        ],
        "profileSummaryTitle": "Summary",
        "profileSummaryDescription": "Shuangquan Zhu is a professional developer who focuses on iOS now. He has strong knowledge of Objective-C, Swift and Javascript. With these skills, he created quite a few quickly developer tools. He also leads the J1 iOS team to promote the project process.\nHe crazy loves playing basketball with friends in spare time, He also loves traveling, writing and listening music. He is always willing to try new things, and keeping to learn from them.",
        "profileInterestTitle": "Interest",
        "profileInterestList": [
            {
                "interest": "Learn about high tech"
            },
            {
                "interest": "Play basketball"
            },
            {
                "interest": "Listen to music"
            },
            {
                "interest": "Apple products"
            }
        ],
        "profileEducationTitle": "Education",
        "profileEducationList": [
            {
                "major": "Business Management",
                "school": "East China University of Science and Technology",
                "year": "2016"
            },
            {
                "major": "Customs and International Freight",
                "school": "Shanghai Maritime Academy",
                "year": "2013"
            }
        ]
    }
}

这个返回的数据结构已经可以完美匹配上图的数据展示需求了.

如何请求

就以第一个模块举例, 我们打开 pc_home.js
为例:

构造函数

constructor() {
        super();
        this.state = {
            data: {
                profileImage: '',
                profileName: '',
                profileCareer: '',
                profileLocation: '',
                profileSocialList: [],
                profileSummaryTitle: '',
                profileSummaryDescription: '',
                profileInterestTitle: '',
                profileInterestList: [],
                profileEducationTitle: '',
                profileEducationList: []
            }
        }
    }

首先我们需要添加构造函数, 字段对应返回的数据结构.

生命周期函数

componentWillMount() {
        GET(URL.fetchProfile).then((data) => {
            this.setState({data: data})
        })
    }

生命周期函数, 用于页面的请求, 我们可以看到对刚才fetch封装类的调用.

渲染函数

render() {
        const {data} = this.state;
        let profileLocation = data.profileLocation.length ? `Location: ${data.profileLocation}` : ''
        let profileSummaryDescription = data.profileSummaryDescription.split('\n').map((description, index) => (
            

{description}

)) let profileSocialList = data.profileSocialList.map((socialVo, index) => (
)) let profileInterestList = data.profileInterestList.map((interestVo, index) => (
  • # {interestVo.interest}
  • )) let profileEducationList = data.profileEducationList.map((educationVo, index) => (
    {educationVo.major} - {educationVo.year}
    {educationVo.school}
    )) return (
    {data.profileName}
    {data.profileCareer}
    {profileLocation}
    {profileSocialList}

    {data.profileSummaryTitle}

    {profileSummaryDescription}

    {data.profileInterestTitle}

      {profileInterestList}

    {data.profileEducationTitle}

    {profileEducationList}
    ) }

    进行渲染, 我们可以将一些逻辑写在render函数中, 就写法而言react这种用起来是比vue的模板v-for这种更适合有经验的开发者.

    这里有一个知识点需要掌握就是当react的jsx需要循环渲染的时候需要在最外面的节点添加key={index}属性.

    完整代码

    import React, {Component} from 'react';
    import CSSModules from 'react-css-modules';
    import styles from './pc_home.css';
    import {GET, URL} from '../javascripts/http';
    
    @CSSModules(styles, {allowMultiple: true})
    export default class PCHome extends Component {
    
        constructor() {
            super();
            this.state = {
                data: {
                    profileImage: '',
                    profileName: '',
                    profileCareer: '',
                    profileLocation: '',
                    profileSocialList: [],
                    profileSummaryTitle: '',
                    profileSummaryDescription: '',
                    profileInterestTitle: '',
                    profileInterestList: [],
                    profileEducationTitle: '',
                    profileEducationList: []
                }
            }
        }
    
        componentWillMount() {
            GET(URL.fetchProfile).then((data) => {
                this.setState({data: data})
            })
        }
    
        render() {
            const {data} = this.state;
            let profileLocation = data.profileLocation.length ? `Location: ${data.profileLocation}` : ''
            let profileSummaryDescription = data.profileSummaryDescription.split('\n').map((description, index) => (
                

    {description}

    )) let profileSocialList = data.profileSocialList.map((socialVo, index) => (
    )) let profileInterestList = data.profileInterestList.map((interestVo, index) => (
  • # {interestVo.interest}
  • )) let profileEducationList = data.profileEducationList.map((educationVo, index) => (
    {educationVo.major} - {educationVo.year}
    {educationVo.school}
    )) return (
    {data.profileName}
    {data.profileCareer}
    {profileLocation}
    {profileSocialList}

    {data.profileSummaryTitle}

    {profileSummaryDescription}

    {data.profileInterestTitle}

      {profileInterestList}

    {data.profileEducationTitle}

    {profileEducationList}
    ) } }

    学会一个接口请求, 对于其他的就是复制黏贴的重复劳动了, 这样这个简历项目的完整性又有了进一步的提升, 接下来的发展方向是制作一个后台服务, 敬请期待.

    About:

    点击下方链接跳转!!

    :star2: 项目源码 请点这里:star2: >>> 喜欢的朋友请点喜欢 >>> 下载源码的同学请送下小星星 >>> 有闲钱的壕们可以进行打赏 >>> 小弟会尽快推出更好的文章和大家分享 >>> 你的激励就是我的动力!!

    您可能感兴趣的

    BiglyBT, new Vuze-based torrent client without ads BiglyBT is a new cross-platform open source torrent client that can be best described as a fork of Vuze / Azureus that is ad-free and without other p...
    Django+Vuejs 集成 WebSocket 实现服务器推送消息架构实践... 到目前为止,我们使用 Django+Vuejs 实现的各种跨平台应用(包括很大一部分的 Cordova Hybrid Apps)实践已有相当一段时间了,有些架构上的限制也逐渐显露出来,比较重要的一点就是在一些消息通知的层面仍然采用低效的 http 轮询的模式,我们希望使用 WebSocket,...
    Super Mario who? HTML5 platformer prototype inspir... About one year ago I showed you how to build a HTML5 platformer prototype inspired by iOS hit “Yeah Bunny” thanks to Phaser and ARCADE physics ...
    iOS进阶补完计划–数据缓存与多线程安全... 通常一个APP分为网络、数据、业务等多个层级。 只看数据层、最基本的模式如下。 VC从DB层读取数据、交由View进行展示。 iOS进阶补完计划-多线程数据缓存-1 然而、当同一个VC需要多次读取、或者多个VC都需要像DB读取数据的...
    广告页结束后要删除广告图片 很多app启动后都会加载一个广告业,我们可以选择跳过或者等它自己消失。但是当这个广告页消失后别忘了删除这个图片!!! 广告图片一般都是高清大图,我们假设广告图片是 1080 x 1920 的,又因为图片在该缓存中的大小是通过像素来衡量的,每个像素占用4个字节,所以我们可以计算出广告页占用多少内存...
    0
    简书

    责编内容来自:简书 (本文源链)
    阅读提示:酷辣虫无法对本内容的真实性提供任何保证,请自行验证并承担相关的风险与后果!
    本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。