normalizr 学习笔记 --- node.js开发
来源:互联网 发布:娇喘合集 网络歌手 编辑:程序博客网 时间:2024/06/05 18:57
normalizr 学习笔记 — node.js开发
最近开始学习node.js开发,有很多基础知识和框架需要学习,所以打算将自己学习笔记记录下来,即可以和大家分享,也可以方便自己以后回顾知识。由于只是个人笔记,便不是详细的教程,有不懂的代码还请自行百度。
主要模块
- normalizr
介绍
该模块主要将获取的数据进一步格式化,在store创建一个虚拟数据库,数据通过id引用
代码段
由于我学习时是配合redux进行使用的,所以这里主要是在redux的基础上进行讲解的,redux的相关内容可参考Redux 学习笔记 — node.js开发,或者自行查找自动学习。
我使用了redux官方的例子real-world中的部分源码,大家可以配合这个学习
import api from '../api'...applyMiddleware(thunk, api, createLogger())
添加real-world的api中间组件
import { Schema, arrayOf, normalize } from 'normalizr'
在api中导入normalizr模块
const historySchema = new Schema('historys', { idAttribute: history => history.ContractID})const userScheme = new Schema('users', { idAttribute: user => user.UserID})const replySchema = new Schema('replys', { idAttribute: reply => reply.ReplyID})userScheme.define({ history: historySchema})historySchema.define({ reply: replySchema})
数据结构定义,define()定义包含的schema
export const Schemas = { HISTORY: historySchema, HISTORY_ARRAY: arrayOf(historySchema), REPLY: replySchema, REPLY_ARRAY: arrayOf(replySchema), USER: userScheme, USER_ARRAY: arrayOf(userScheme)}
输出数据结构模板,arrayOf()模板数组化
const API_ROOT = 'http://localhost/app/'function callApi(endpoint, schema, method, form) { const fullUrl = (endpoint.indexOf(API_ROOT) === -1) ? API_ROOT + endpoint : endpoint let requestType; if (method === 'POST') { requestType = { method: method, body:form } } else if (method === 'GET') { requestType = null } return fetch(fullUrl, requestType) .then(response => { return response.json() .then(json => ({ json, response }) ) }) .then(({ json, response }) => { if (!response.ok) { // 回调规范的处理失败格式 return Promise.reject(json) } if (json.code !== 200) { // 回调规范的处理失败格式 return Promise.reject(json) } return Object.assign({},normalize(json.data, schema)) })}
根据action传过来的参数,进行不同的网络请求,请求成功后的数据通过normalize()进行转换
// action keyexport const CALL_API = 'CALL_API'export default store => next => action => { const callAPI = action[CALL_API] if (typeof callAPI === 'undefined') { return next(action) } let { endpoint, method, form } = callAPI const { schema, types } = callAPI if (typeof endpoint === 'function') { endpoint = endpoint(store.getState()) } if (typeof endpoint !== 'string') { throw new Error('Specify a string endpoint URL.') } if (!schema) { throw new Error('Specify one of the exported Schemas.') } if (!Array.isArray(types) || types.length !== 3) { throw new Error('Expected an array of three action types.') } if (!types.every(type => typeof type === 'string')) { throw new Error('Expected action types to be strings.') } function actionWith(data) { const finalAction = Object.assign({}, action, data) delete finalAction[CALL_API] return finalAction } const [ requestType, successType, failureType ] = types next(actionWith({ type: requestType })) return callApi(endpoint, schema, method, form).then( response => next(actionWith({ response, type: successType })), error => next(actionWith({ type: failureType, error: error.message || 'Something bad happened' })) )}
分为3个action请求阶段,requestType, successType,failureType,根据callApi()返回的结构进行异步调用,此时数据已经存入store中的虚拟数据库,之后将action传给真正的reduce将id数据存入
import _ from 'lodash'...function entities(state = { users: {}, historys: {}, replys: {}}, action) { if (action.response && action.response.entities) { return _.merge({}, state, action.response.entities) } return state}
这里用到lodash模块的merge,将所有请求获取到的数据和store虚拟数据库进行合并更新
const pagination = combineReducers({ historyBySection: paginate({ mapActionToKey: action => action.section, types: [ ActionTypes.HISTORY_REQUEST, ActionTypes.HISTORY_SUCCESS, ActionTypes.HISTORY_FAILURE ] }), replyByHistory: paginate({ mapActionToKey: action => action.historyId, types: [ ActionTypes.REPLY_REQUEST, ActionTypes.REPLY_SUCCESS, ActionTypes.REPLY_FAILURE ] })})
根据不同类型实现数据分页的接口,mapActionToKey作为类型指针,type接收的ActionTypes
import merge from 'lodash/merge'import union from 'lodash/union'// Creates a reducer managing pagination, given the action types to handle,// and a function telling how to extract the key from an action.export default function paginate({ types, mapActionToKey }) { if (!Array.isArray(types) || types.length !== 3) { throw new Error('Expected types to be an array of three elements.') } if (!types.every(t => typeof t === 'string')) { throw new Error('Expected types to be strings.') } if (typeof mapActionToKey !== 'function') { throw new Error('Expected mapActionToKey to be a function.') } const [ requestType, successType, failureType ] = types function updatePagination(state = { isFetching: false, ids: [] }, action) { switch (action.type) { case requestType: return merge({}, state, { isFetching: true }) case successType: return merge({}, state, { isFetching: false, ids: union(state.ids, action.response.result), }) case failureType: return merge({}, state, { isFetching: false }) default: return state } } return function updatePaginationByKey(state = {}, action) { switch (action.type) { case requestType: case successType: case failureType: const key = mapActionToKey(action) if (typeof key !== 'string') { throw new Error('Expected key to be a string.') } return merge({}, state, { [key]: updatePagination(state[key], action) }) default: return state } }}
实现数据分页方法,配合了normalizr
function mapStateToProps(state, ownProps) { const section = ownProps.section; const { pagination: { historyBySection }, entities: { historys } } = state; const historyPagination = historyBySection[section] || { isFetching: true, ids: [] } const items = historyPagination.ids.map(id => historys[id]) return { historyPagination, items }}
根据分页指针和reduce中的id,从store虚拟数据库中获取真正的数据
部分代码来自于redux官方例子real-world
- normalizr 学习笔记 --- node.js开发
- Node.js开发指南学习笔记
- Parse Server 学习笔记 --- node.js开发
- Redux 学习笔记 --- node.js开发
- webpack 学习笔记 --- node.js开发
- ES6/ES7学习笔记 --- node.js开发
- Node.JS学习笔记
- node.js学习笔记
- Node.js 学习笔记
- node.js学习笔记
- node.js 学习笔记
- Node.js 学习笔记
- Node js 学习笔记
- Node.js学习笔记
- node.js学习笔记
- Node.js学习笔记
- node.js学习笔记
- node.js学习笔记
- Unity 函数延迟调用
- 文章标题
- 强制横屏的一种实现 ios
- Python爬虫urllib2笔记(二)
- Python中使用matPlotlib绘图-曲线图、柱状图、散列点
- normalizr 学习笔记 --- node.js开发
- 思科路由器防火墙如何配置的方法
- iOS应用跳转至app store 评分页(包括iOS7前后两种)
- 后缀数组 POJ 3693 && hdu 2459 Maximum repetition substring
- STL 容器的排序
- Window域管理命令
- jquery 弹窗插件 layer
- Android四大组件之Activity(七大生命周期)
- libevent2.0源码学习三:对网络模型的(EPOLL)的封装