react-native-async-cache
Getting started
$ npm install react-native-async-cache --save
Mostly automatic installation
$ react-native link react-native-async-cache
API
Promise select(options)
The only method need to know, return a promise resolves an object containing url.
If the file downloaded, resolve the url as local path, otherwise resolve the request given.
| Option | Optional | Type | Description |
|---|
| url | NO | String | the network resource url |
| headers | YES | Map<String,String> | http request headers |
| subDir | YES | String | name of directory where the file save to |
| extension | YES | String | file extension (e.g ''.jpg" or "jpg") |
| id | YES | String | file unique identification, advance usage |
| data | YES | String | binary custom data |
| dataType | YES | String | type of custom data, "text", "base64" or "base64Url" |
| sign | YES | String | file identification obfuscation |
| Param | Type | Description |
|---|
| success | Boolean | whether the file is cached |
| url | String | the url from given request or the file path prefix with file:// that been cached |
| statusCode | Integer | it's nonzero and nonnull if request failed |
| message | String | the failure description |
import React from "react";
import RNAsyncCache from 'react-native-async-cache';
export default class extends React.Component
{
componentDidMount(){
RNAsyncCache.select({
url: "https://static.zerochan.net/Kouyafu.full.2927619.jpg"
}).then((res) => {
const {url, statusCode, message} = res;
this.setState(
{img: url, statusCode, message}
);
});
}
// Component initial state
state = {
img:"",
statusCode: 0,
message:""
};
// Component render
render()
{
const {img, statusCode, message} = this.state;
if(statusCode || message){
// request failed
return <Text>{statusCode} {message}</Text>;
}
return img ? <Text>Loading...</Text>: <Image source={{uri: img}}/>;
}
}
Promise trash(options)
Empty the cache directory.
| Option | Optional | Type | Description |
|---|
| subDir | YES | String | name of directory be emptied |
Promise accessible(options)
Try to check http status code of the url is 200 OK.
| Option | Optional | Type | Description |
|---|
| url | NO | String | network resource url |
| statusCodeLeft | YES | Integer | min valid status code |
| statusCodeRight | YES | Integer | max valid status code |
| accessibleMethod | YES | String | http method, default "HEAD" |
| headers | YES | Map<String,String> | request headers |
| Param | Type | Description |
|---|
| accessible | Boolean | whether the file is cached |
| statusCode | String | http status code or -1 if runtime exception occurred |
| message | String | description of failure |
| size | Number | total bytes of resource, may be -1 if server not support Content-Length |
| url | String | request url |
import React from "react";
import RNAsyncCache from 'react-native-async-cache';
import {Image, Text} from "react-native";
export default class extends React.Component {
state = {
error:""
};
render(){
const {error} = this.state;
const img = "https://i.pximg.net/img-master/img/2020/04/04/00/10/00/80545109_p0_master1200.jpg";
return error ? (<Text>{error}</Text>) : <Image source={{uri:img}} onError={()=>{
RNAsyncCache.accessible({
url:img
}).then(({statusCode, message})=>{
this.setState({
error: statusCode + "\n" + message
});
});
}} />
}
}
Promise check(options)
Confirm whether the cache file exists.
| Option | Optional | Type |
|---|
| url | NO | String |
| subDir | YES | String |
| extension | YES | String |
| Param | Type | Description |
|---|
| path | String | not empty if the file exists |
| exists | Boolean | whether the file exists |
| url | String | request url |
Promise remove(options)
Delete the cache file specified.
| Option | Optional | Type |
|---|
| url | NO | String |
| subDir | YES | String |
| extension | YES | String |
| Param | Type | Description |
|---|
| success | String | whether the file was deleted successfully |
| path | Boolean | path of the file be deleted, it's not empty if successfully removed |
| url | String | request url |
Promise download(options, onProgress)
Cache a file manually.
| Option | Optional | Type |
|---|
| url | NO | String |
| subDir | YES | String |
| extension | YES | String |
| headers | YES | Map<String,String> | request headers |
| Param | Type | Description |
|---|
| progress | Number | less than 1, always 0 if total is -1 |
| total | Boolean | -1 if server not support Content-Length |
| current | String | bytes of written |
| url | String | request url |
| Param | Type | Description |
|---|
| size | Number | the size of the file been downloaded |
| path | Boolean | path of the file |
| url | String | request url |
void post(options)
delegate a background download task or create a cache with url and exists data.
| Option | Optional | Type |
|---|
| url | NO | String |
| headers | YES | Map<String,String> |
| subDir | YES | String |
| extension | YES | String |
| headers | YES | Map<String,String> | request headers |
| data | YES | String | custom data |
| dataType | YES | String | "text", bianary use "base64" or "base64Url" |
Cache Component
| Option | Optional | Type | Description |
|---|
| Component | NO | Component | render component with url |
| PendingComponent | YES | Component | render component during select() execution |
| mapToRequestOptions | YES | Function | map component props to request options |
| mapToComponentProperties | YES | Function | map select() result to component props |
| sourceProperty | YES | String | name of the component property, default 'source' |
| invokeOnComponentErrorProperty | YES | String | name of the callback function invoked on load error |
| invokeOnComponentLoadProperty | YES | String | name of the callback function invoked on load success |
| sourceMapper | YES | Function | map url to local path |
| onSourceMapped | YES | Function | invoked on url accepted |
| onRequestError | YES | Function | invoked on url has been checked not accessible |
| cacheValidator | YES | Function | confirm the cache is valid, usually not need it |
Usage
import {CacheComponent} from 'react-native-async-cache';
import {Image,View} from 'react-native';
const CacheImage = CacheComponent(
{
Component: Image,
PendingComponent: Image,
invokeOnComponentErrorProperty: 'onError',
invokeOnComponentLoadProperty: 'onLoad',
mapToRequestOptions: () => {
return {
subDir: 'images'
};
},
mapToComponentProperties: (props) => {
return {
source: typeof props.source === 'number' ? props.source : {uri: props.source},
errorMessage: (props.statusCode || props.message) ? props.statusCode + ' ' + (props.message || '') : null
};
}
}
);
// render component
export default class extends React.Component
{
render(){
return (
<View style={{flex: 1, alignItems: "center"}}>
<CacheImage source={"https://static.zerochan.net/Kouyafu.full.2792022.jpg"}
style={{
width : Dimensions.get("window").width - 30,
height : Dimensions.get("window").height
}}
/>
</View>
);
}
}
CacheStoreComponent
create a CacheComponent with a memory store to reduce select() calls.
import {CacheStoreComponent} from 'react-native-async-cache';
import {Text,View,Image} from "react-native";
const CacheStoreImage = CacheStoreComponent(
{
Component: Image,
PendingComponent: ()=>{
return <View><Text>Loading...</Text></View>;
},
invokeOnComponentErrorProperty: 'onError',
invokeOnComponentLoadProperty: 'onLoad',
mapToRequestOptions: () => {
return {
subDir: 'images'
};
},
mapToComponentProperties: (props) => {
return {
source: typeof props.source === 'number' ? props.source : {uri: props.source},
errorMessage: (props.statusCode || props.message) ? props.statusCode + ' ' + (props.message || '') : null
};
}
}
);
// render component
export default ()=>{
return (
<View style={{flex: 1, alignItems: "center"}}>
<CacheStoreImage source={"https://static.zerochan.net/Fuji.Choko.full.2920380.jpg"} style={{
width : Dimensions.get("window").width - 30,
height : Dimensions.get("window").height
}}/>
</View>
);
}
- Custom StoreProvider Example
import {CacheStoreComponent, StoreProvider} from 'react-native-async-cache';
import AsyncStorage from 'react-native-async-storage';
// extend default StoreProvider
class PersistenceStoreProvider extends StoreProvider {
access_time = 0;
constructor(props) {
super(props);
AsyncStorage.getItem('caches').then(str=>{
this.caches=JSON.parse(str);
});
}
get(url){
++this.access_time;
if(this.access_time > 100){
this.access_time = 0;
this.serialize();
}
return super.get(url);
}
serialize(){
// call it at the right time
AsyncStorage.setItem('caches',JSON.stringify(caches));
}
clear(){
// optional, call it when local file not found
this.caches = [];
AsyncStorage.setItem('caches',JSON.stringify([]));
}
}
// create CacheStoreComponent
export default CacheStoreComponent({
store: new PersistenceStoreProvider(),
// ...
});
// improt fs from "react-native-fs";
// config
const config = {
store: new PersistenceStoreProvider(),
// ...
cacheValidator:(cache,callback)=>{
if(cache && !cache.local){
callback(cache);
}
else {
fs.exists(cache).then(exists=>{
callback(exists ? cache : null);
if(!exists)
{
config.store.clear();
}
});
}
}
}
export default CacheStoreComponent(config);
- Advanced usage, StoreProvider interface
interface StoreProvider {
get(url: string): string;
set(url: string, local: string): void;
error(url: string, code: number, message: string): void
}
| Callback Method | Description |
|---|
| get | return nullable cache file path with url |
| set | associate local path to url |
| error | invoked if resource is inaccessible |