typescript - use map

  • Commit 
https://github.com/shooeugenesea/study-js/commit/2d22117a7b36ea1225b960892995e409bbc5e64f
    https://github.com/shooeugenesea/study-js/commit/30cb24cd3a5dc57dde750fa6e90a04b88dba8084
    • Declare class with map
    • export class TestMap {
          private map: Map<string, string> = new Map();

          put(key:string, val:string): void {
              if (key) {
                  this.map.set(key, val);
              }
          }

          get(key:string): string | undefined {
              if (key) {
                  return this.map.get(key)
              }
          }

          count(): number {
              return this.map.size;
          }

          clearByKeyPrefix(prefix: string) {
              this.map.forEach((v: string, k:string, m:Map<string,string>) => {
                  if (k.startsWith(prefix)) {
                      m.delete(k);
                  }
              })
          }
      }
    • Put and get then print
    • const testMap = new TestMap();
      testMap.put("ka", "vka");
      testMap.put("kb", "vka");
      testMap.put("kc", "vka");
      testMap.put("kd", "vka");
      testMap.put("ke", "vka");
      testMap.put("aa", "vaa");
      console.log(testMap);
      console.log(testMap.count()); // 6
      testMap.clearByKeyPrefix("k"); // print 6 entries
      console.log(testMap.get("aa")); // print vaa


    redux - typescript - change index.js to support typescript

    Git Commit

    • Install typescript
    npm install --save-dev typescript
    • New Helloworld.ts
    export class Helloworld {
        public name: String;

        public constructor(name:String) {
            this.name = name;
        }

        public greeting(): void {
            console.log(`Helloworld! ${this.name}`);
        }
    }
    • New TodoItem.ts
    export class TodoItem {
        public constructor(public id:String, public task:String, public done:boolean) {
        }

        public printDetail():void {
            console.log(`${this.id} / ${this.task} / ${this.done}`);
        }
    }
    • New TodoItemCollection.ts
    import {TodoItem} from "./TodoItem";

    export class TodoItemCollection {
        constructor(public name:String, public todoItems: TodoItem[]) {
        }

        public addItem(item: TodoItem): number {
            return this.todoItems.push(item);
        }

        public getItemById(id:String): TodoItem | undefined {
            return this.todoItems.find(item => item.id === id);
        }

        public markDone(id:String) {
            const item = this.getItemById(id)
            if (item) {
                item.done = true
            }
        }
    }
    • Rename index.js to index.tsx
    import React from 'react';
    import ReactDOM from 'react-dom';
    import App from './App';
    import {createStore, applyMiddleware} from 'redux'
    import { Provider } from 'react-redux'
    import reducers from './reducers'
    import thunk from "redux-thunk";
    import {Helloworld} from './ts/Helloworld'
    import {TodoItemCollection} from "./ts/TodoItemCollection";
    import {TodoItem} from "./ts/TodoItem";

    const store = createStore(reducers, applyMiddleware(thunk));

    ReactDOM.render(
          <Provider store={store} >
              <App />
          </Provider>,
      document.getElementById('root')
    );

    const h = new Helloworld("KKK");
    h.greeting();

    const todos = new TodoItemCollection("name1", [
        new TodoItem("id1", "task1", false),
        new TodoItem("id2", "task2", false),
        new TodoItem("id3", "task3", false),
    ]);
    todos.addItem(new TodoItem("id4", "task4", false));
    console.log(todos);
    todos.markDone("id2");
    console.log(todos.getItemById("id2"));
    • Check typescript works


    redux - redux thunk - prevent duplicated request


    =================== Prepare ========================
    • whenever we dispatch a function, redux pick it up and invoke it
    export const fetchPostsAndUsers = () => async dispatch => {
        await // need await because invoking an async function and we want to wait until it's done
            dispatch( // dispatch an "async dispatch..." function, so invoke it directly
                fetchPosts() // call export const fetchPosts = ()
                             // and return "async dispatch => { ... }"
            )
    }

    export const fetchPosts = () => async dispatch => {
        const response = await jsonPlaceholder.get('/posts')

        dispatch({type:'FETCH_POSTS', payload: response.data})
    }
    Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters.
    If a property name is provided for iteratee the created _.property style callback returns the property value of the given element.
    Creates a duplicate-free version of an array, using SameValueZero for equality comparisons, in which only the first occurrence of each element is kept. The order of result values is determined by the order they occur in the array.

    ===================== Need to change =================
    • Remove memoize function
    export const fetchUser = (userId) => async dispatch => {
        const response = await jsonPlaceholder.get(`/users/${userId}`)

        dispatch({type:'FETCH_USER', payload: response.data})
    }
    • Create fetchPostsAndUsers function
    export const fetchPostsAndUsers = () => async (dispatch, getState) => {
        await dispatch (fetchPosts());
        const userIds = _.uniq(_.map(getState().fetchPosts, 'userId'))
        userIds.forEach(id => dispatch(fetchUser(id)))
    }
    • Fetch posts and users from PttPosts.js
    import React, {Component} from "react";
    import {connect} from 'react-redux'
    import {fetchPostsAndUsers, selectPttPost} from "../actions";
    import UserHeader from "./UserHeader";

    class PttPosts extends Component {
        componentDidMount() {
            this.props.fetchPostsAndUsers()
        }

        renderList() {
            if (this.props.postList) {
                return this.props.postList.map((post) => {
                    return <div key={post.id}>
                        <div key={post.id}><a onClick={() => this.props.selectPttPost(post)}>Title:{post.title}</a></div>
                        <UserHeader userId={post.userId} />
                    </div>
                });
            } else {
                return 'Loading...'
            }
        };

        render() {
            return <div>{this.renderList()}</div>
        }
    }

    const mapStateToProps = (state) => {
        return {postList: state.fetchPosts};
    }

    export default connect(mapStateToProps, { fetchPostsAndUsers, selectPttPost })(PttPosts)
    • Don't need fetchUsers from UserHeader.js
    import React, {Component} from "react";
    import {connect} from 'react-redux'
    import {fetchUser} from "../actions";

    class UserHeader extends Component {

        componentDidMount() {
            this.props.fetchUser(this.props.userId)
        }

        render() {
            return <div>Author: {this.props.user?.name}</div>
        }
    }

    const mapStateToProps = (state, props) => {
        return {user: state.users?.find(user => user.id === props.userId)}
    }

    export default connect(mapStateToProps, {fetchUser})(UserHeader)
    • Duplicated requests disappear


    別名演算法 Alias Method

     題目 每個伺服器支援不同的 TPM (transaction per minute) 當 request 來的時候, 系統需要馬上根據 TPM 的能力隨機找到一個適合的 server. 雖然稱為 "隨機", 但還是需要有 TPM 作為權重. 解法 別名演算法...