1.0.3 • Published 6 months ago
@casipe/react-service-provider v1.0.3
react-lib-chat-front
aka react-service-provider
Service Provider is an asynchronous resource to an application make requests to APIs, these providers also manage the requests, retrying failed requests, and also provide a local storage cache.
The application will able to do any HTTP request and navigate to other resources without lose these request.
- Retry failed request by number of retries
- Retry failed request by timeout
- Cache with TTL
- Use Observables
Installation
npm install --save-dev @casipe/react-service-provider@latest
Pipeline status by branch
publish-legacy
N/A
publish
publish-next
N/A
Usage
Custom service class
import { Service } from '@casipe/react-service-provider'
class FooService extends Service {
// config service behavior
public requestConfig = {
retriesTimeout: 1000,
retryDelay: 200
}
observableBased() {
return this.request({
url: this.params.API_URL_FOO,
headers: {
key: this.getProp('key') // prop of ServiceProvider
}
})
}
promiseBased() {
return this.requestAsync({
url: this.params.API_URL_FOO,
headers: {
key: this.getProp('key') // prop of ServiceProvider
}
})
}
}// App.jsx
import { ServiceProvider } from '@casipe/react-service-provider'
import { useConfig } from '@casipe/react-app-context'
const services = [FooService] => {
const appContextConfig = getConfig()
const token = '<TOKEN>'
return (
<ServiceProvider services={services} authorizationToken={token} config={appContextConfig}>
<Component />
</ServiceProvider>
)
}import { useObservable, useServices } from '@casipe/react-service-provider'
export const Component = () => {
const [fooService] = useServices(FooService)
const [foo, setFoo] = useRequest<FruitInterface[]>([])
useEffect(() => {
const subscriber = fooService.observableBased().subscribe( response => {
setFoo(response)
})
return () => {
subscriber.unsubscribe()
}
}, [])
return (
<div>
{foo.isCached && 'CACHED'}
{foo.error && <h1>{list.error?.message}</h1>}
{foo.isLoading && <div>...loading</div>}
{!foo.isLoading && list.data && (
<div>{foo.data?.map(fruitItemComponent)}</div>
)}
</div>
)
}Connect to web socket
SocketIO Configuration
const App: FC = () => {
const config = useConfig()
const socketIo: SocketIOConfigInterface = {
url: config.SOCKETIO_URL,
namespaces: [USER_ID_FROM_TOKEN, MERCHANT_ID_FROM_TOKEN],
socketIoOptions: {
extraHeaders: { hello: 'message', Authorization: TOKEN_FROM_SESSION }
}
}
return (
<ServiceProvider
config={config}
services={[ChatService]}
socketIo={socketIo} // SocketIOConfigInterface
authorizationToken={TOKEN_FROM_SESSION}
>{...}</ServiceProvider>
)
}Usage
- This example's about an incoming chat message from WebSocket
- The WS service doesn't send messages through socket just receive
- Send request through REST
- Wait response through websocket
// services/ChatService.ts
export interface ChatPayloadInterface {
message: string
}
export class ChatService extends Service<DemoAppParams> {
private chatSubject = new ReplaySubject<string>(Infinity)
public chat$ = this.chatSubject.asObservable()
public init() {
this.socket<ChatPayloadInterface>('chat')
.pipe(map((message) => message.payload.message))
.subscribe(this.chatSubject)
}
}Solutions
- Messages to user and user groups, is posted to a namespace, configure these namespaces on SocketIOConfigInterface object.
- Use action to identify behavior in service
- Use payload to identify a document inside the application
- When you expect a message for a specific job, use the jobId method to control this flow, see an example in the demo