function createStore(reducer){ let state = reducer(undefined, {}) let cbs = [] const getState = () => state const subscribe = cb => (cbs.push(cb), () => cbs = cbs.filter(c => c !== cb)) const dispatch = action => { if (typeof action === 'function'){ return action(dispatch, getState) } const newState = reducer(state, action) if (newState !== state){ state = newState for (let cb of cbs) cb() } } return { getState, dispatch, subscribe } } const getGQL = url => (query, variables) => fetch(url, { method: 'POST', headers: { "Content-Type": "application/json", // 'Accept' : 'application/json', ...(localStorage.authToken ? {"Authorization": "Bearer " + localStorage.authToken} : {}) }, body: JSON.stringify({query, variables}) }).then(res => res.json()) .then(data => { if (data.data){ return Object.values(data.data)[0] } else throw new Error(JSON.stringify(data.errors)) }) const backendURL = 'http://shop-roles.asmer.fs.a-level.com.ua' const gql = getGQL(backendURL + '/graphql'); function promiseReducer(state={}, {type, name, status, payload, error}){ if (type === 'PROMISE'){ return { ...state, [name]:{status, payload, error} } } return state } const actionPending = name => ({type:'PROMISE',name, status: 'PENDING'}) const actionFulfilled = (name,payload) => ({type:'PROMISE',name, status: 'FULFILLED', payload}) const actionRejected = (name,error) => ({type:'PROMISE',name, status: 'REJECTED', error}) const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms)) const store = createStore(promiseReducer); store.subscribe(() => console.log(store.getState())) //store.dispatch(actionPending('delay1000')) ////{ 1 //// delay1000: {status: 'PENDING'} ////} //delay(1000).then(result => store.dispatch(actionFulfilled('delay1000', result))) ////{ 3 //// delay1000: {status: 'FULFILLED', payload: 1000}, //// delay2000: {status: 'PENDING'} ////} //store.dispatch(actionPending('delay2000')) ////{ 2 //// delay1000: {status: 'PENDING'}, //// delay2000: {status: 'PENDING'} ////} //delay(2000).then(result => store.dispatch(actionFulfilled('delay2000', result))) ////{ 4 //// delay1000: {status: 'FULFILLED', payload: 1000}, //// delay2000: {status: 'FULFILLED', payload: 2000} ////} const actionPromise = (name, promise) => async dispatch => { dispatch(actionPending(name)) try { let payload = await promise dispatch(actionFulfilled(name, payload)) return payload } catch(error){ dispatch(actionRejected(name, error)) } } store.dispatch(actionPromise('delay1000', delay(1000))) store.dispatch(actionPromise('delay2000', delay(2000))) const actionLuke = () => actionPromise('luke', fetch('https://swapi.dev/api/people/1') .then(res => res.json())) store.dispatch(actionLuke()) const actionRegister = (login, password) => actionPromise('register', gql( `mutation register($login: String, $password: String) { UserUpsert(user: {login: $login, password: $password}) { _id login } }`, {login : login, password : password})) store.dispatch(actionRegister('user777', '777')); const actionCategoryById = (_id) => actionPromise('catById', gql(`query catById($q: String){ CategoryFindOne(query: $q){ _id name goods { _id name price images { url } } } }`, {q: JSON.stringify([{_id}])})); store.dispatch(actionCategoryById("5dc458985df9d670df48cc47")); const actionGoodById = (_id) => actionPromise('goodById', gql(`query goodByid($goodId: String) { GoodFindOne(query: $goodId) { name price description images { url } } }`, {goodId: JSON.stringify([{_id}])})) store.dispatch(actionGoodById("5dc4a3e15df9d670df48cc6b")); const actionRootCategories = () => actionPromise('rootCats', gql(`query { CategoryFind(query: "[{\\"parent\\":null}]"){ _id name } }`)) store.dispatch(actionRootCategories()); const actionNewOrder = (order) => actionPromise('newOrder', gql( `mutation newOrder($order: OrderInput) { OrderUpsert(order: $order) { _id total } }`, {order : order} ) ) let order = { orderGoods: [ {count: 2, good: {_id: "5dcac57d6d09c45440d14cfc"}}, {count: 2, good: {_id: "5dcac9ba6d09c45440d14d02"}}, {count: 1, good: {_id: "5dc8844e0e36db246e3049bd"}}, ] } store.dispatch(actionNewOrder(order)); const actionOrders = () => actionPromise('allOrders', gql(`query findOrder($q: String) { OrderFind(query: $q) { _id total orderGoods { count good { name price } } } }`, {q: JSON.stringify([{}])})) store.dispatch(actionOrders())