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> |
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> |
data |
YES |
String |
dataType |
YES |
String |
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 |