Skip to content

Commit

Permalink
feat: add syncOptions, and refactor test/ (#23)
Browse files Browse the repository at this point in the history
* feat: close #22, add syncOptions

* refactor(test): use async/await, map -> forEach

* fix: replace NODE_ENV to use it in the browser
  • Loading branch information
BuptStEve authored Mar 5, 2019
1 parent d1812b5 commit 02cfd36
Show file tree
Hide file tree
Showing 9 changed files with 557 additions and 604 deletions.
18 changes: 18 additions & 0 deletions docs/config-methods/methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,24 @@ async () => {

调用同步函数时传递参数。

### syncOptions 同步函数配置 <Badge text="1.7.0+"/>
* 类型:`Any`
* 默认值:`[]`

因为 `syncFn` 默认只接受 `syncParams` 作为参数,在使用时不太方便。尤其是搭配 [tua-api](https://tuateam.github.io/tua-api/) 使用时,没法方便地传递 [运行时配置](https://tuateam.github.io/tua-api/config/runtime.html)

因此添加了 `syncOptions` 用于传递 `syncFn` 函数的其他参数。

`syncOptions` 类型为数组时,以这样的方式调用。

```js
syncFn(syncParams, ...syncOptions)
```

即数组的各个元素分别作为 `syncFn` 的第二个到第 n 个参数。

其他类型时,以这样的方式调用 `syncFn(syncParams, syncOptions)`,即作为第二个参数。

### fullKey 完整关键词
* 类型:`String`
* 默认值:`''`
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "tua-storage",
"version": "1.6.0",
"version": "1.7.0",
"description": "🏗 A common storage for web(localStorage), for RN(AsyncStorage), for mini-program(wx) or just memory cache(Node.js)",
"main": "dist/TuaStorage.cjs.js",
"module": "dist/TuaStorage.esm.js",
Expand Down Expand Up @@ -99,6 +99,7 @@
"rollup-plugin-babel": "^4.3.2",
"rollup-plugin-eslint": "^5.0.0",
"rollup-plugin-json": "^3.1.0",
"rollup-plugin-replace": "^2.1.0",
"rollup-plugin-uglify": "^6.0.2",
"vuepress": "^1.0.0-alpha.39"
},
Expand Down
17 changes: 15 additions & 2 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json from 'rollup-plugin-json'
import babel from 'rollup-plugin-babel'
import replace from 'rollup-plugin-replace'
import { eslint } from 'rollup-plugin-eslint'
import { uglify } from 'rollup-plugin-uglify'

Expand Down Expand Up @@ -33,16 +34,28 @@ const plugins = [
json(),
babel(),
]
const env = 'process.env.NODE_ENV'

export default [{
input,
output: [ output.cjs, output.esm, output.umd ],
output: [ output.cjs, output.esm ],
plugins,
}, {
input,
output: output.umd,
plugins: [
...plugins,
replace({ [env]: '"development"' }),
],
}, {
input,
output: {
...output.umd,
file: 'dist/TuaStorage.umd.min.js',
},
plugins: [ ...plugins, uglify() ],
plugins: [
...plugins,
replace({ [env]: '"production"' }),
uglify(),
],
}]
7 changes: 5 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ class TuaStorage {
* @param {Number} item.expires 超时时间(单位:秒)
* @param {Object} item.cacheData 缓存数据
* @param {Object} item.syncParams 同步参数对象
* @param {Object} item.syncOptions 同步函数配置
* @param {Boolean} item.isAutoSave 是否自动保存
* @return {Promise}
*/
Expand All @@ -473,6 +474,7 @@ class TuaStorage {
expires,
cacheData,
syncParams,
syncOptions = [],
isAutoSave = true,
}) {
const isNoCacheData = cacheData === null || cacheData === undefined
Expand All @@ -485,15 +487,16 @@ class TuaStorage {

if (err) {
logger.error(err)

return pRej(err)
}
}

// 如果有相同的任务,则共用该任务
if (sameTask) return sameTask.task

const originTask = syncFn(syncParams)
const originTask = Array.isArray(syncOptions)
? syncFn(syncParams, ...syncOptions)
: syncFn(syncParams, syncOptions)
const isPromise = !!(originTask && originTask.then)

if (!isPromise) return pRej(Error(ERROR_MSGS.promise))
Expand Down
5 changes: 3 additions & 2 deletions src/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
* @param {any} out 具体的输出内容
*/
const logByType = (type) => (...out) => {
/* istanbul ignore else */
if (process.env.NODE_ENV === 'test') return
const env = process.env.NODE_ENV
/* istanbul ignore next */
if (env === 'test' || env === 'production') return

/* istanbul ignore next */
console[type](`[TUA-STORAGE]:`, ...out)
Expand Down
202 changes: 92 additions & 110 deletions test/AsyncStorage.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,35 +41,32 @@ describe('timers', () => {
Date.now = jest.fn(() => +new Date())
})

test('setInterval to clean expired data', () => (
tuaStorage
.save([
{ key: `${key}1`, data, syncParams, expires: 10 },
{ key: `${key}2`, data, syncParams, expires: TIME_OUT * 1.5 / 1000 },
{ key: `${key}3`, data, syncParams, expires: TIME_OUT * 2.5 / 1000 },
])
.then(() => {
Date.now = jest.fn(() => TIME_OUT + (+new Date()))
jest.advanceTimersByTime(TIME_OUT)

// 因为删除是异步操作
setImmediate(() => {
expect(getObjLen(cache)).toBe(2)
expect(store.size).toBe(2)
expect(store.get(getTargetKey(`${key}1`))).toBeUndefined()
})
})
.then(() => {
Date.now = jest.fn(() => TIME_OUT * 2 + (+new Date()))
jest.advanceTimersByTime(TIME_OUT * 2)

// 因为删除是异步操作
setImmediate(() => {
expect(getObjLen(cache)).toBe(1)
expect(store.size).toBe(1)
})
})
))
test('setInterval to clean expired data', async () => {
await tuaStorage.save([
{ key: `${key}1`, data, syncParams, expires: 10 },
{ key: `${key}2`, data, syncParams, expires: TIME_OUT * 1.5 / 1000 },
{ key: `${key}3`, data, syncParams, expires: TIME_OUT * 2.5 / 1000 },
])

Date.now = jest.fn(() => TIME_OUT + (+new Date()))
jest.advanceTimersByTime(TIME_OUT)

// 因为删除是异步操作
setImmediate(() => {
expect(getObjLen(cache)).toBe(2)
expect(store.size).toBe(2)
expect(store.get(getTargetKey(`${key}1`))).toBeUndefined()
})

Date.now = jest.fn(() => TIME_OUT * 2 + (+new Date()))
jest.advanceTimersByTime(TIME_OUT * 2)

// 因为删除是异步操作
setImmediate(() => {
expect(getObjLen(cache)).toBe(1)
expect(store.size).toBe(1)
})
})
})

describe('initial state', () => {
Expand All @@ -78,110 +75,95 @@ describe('initial state', () => {
AsyncStorage.clear()
})

test('clean initial expired data', () => (
Promise
.all([
AsyncStorage.setItem(`${DEFAULT_KEY_PREFIX}1`, getExpectedVal(data, -10)),
AsyncStorage.setItem(`${DEFAULT_KEY_PREFIX}2`, stringify({})),
AsyncStorage.setItem(`${DEFAULT_KEY_PREFIX}3`, 'abc'),
AsyncStorage.setItem(`${DEFAULT_KEY_PREFIX}4`, getExpectedVal(data, 10)),
])
.then(tuaStorage._clearExpiredData.bind(tuaStorage))
.then(() => {
const store = AsyncStorage.getStore()

expect(store.size).toBe(3)
expect(store.get(`${DEFAULT_KEY_PREFIX}1`)).toBeUndefined()
})
))

test('clear items not match prefix', () => (
Promise
.all([
AsyncStorage.setItem('b', '666'),
AsyncStorage.setItem('steve', '1217'),
AsyncStorage.setItem(DEFAULT_KEY_PREFIX, '666'),
])
.then(() => (
tuaStorage.clear(['steve', DEFAULT_KEY_PREFIX])
))
.then(() => {
const store = AsyncStorage.getStore()

expect(store.size).toBe(2)
expect(store.get('steve')).toBe('1217')
expect(store.get(DEFAULT_KEY_PREFIX)).toBe('666')
})
))
test('clean initial expired data', async () => {
await Promise.all([
AsyncStorage.setItem(`${DEFAULT_KEY_PREFIX}1`, getExpectedVal(data, -10)),
AsyncStorage.setItem(`${DEFAULT_KEY_PREFIX}2`, stringify({})),
AsyncStorage.setItem(`${DEFAULT_KEY_PREFIX}3`, 'abc'),
AsyncStorage.setItem(`${DEFAULT_KEY_PREFIX}4`, getExpectedVal(data, 10)),
])
await tuaStorage._clearExpiredData()

const store = AsyncStorage.getStore()

expect(store.size).toBe(3)
expect(store.get(`${DEFAULT_KEY_PREFIX}1`)).toBeUndefined()
})

test('clear items not match prefix', async () => {
await Promise.all([
AsyncStorage.setItem('b', '666'),
AsyncStorage.setItem('steve', '1217'),
AsyncStorage.setItem(DEFAULT_KEY_PREFIX, '666'),
])
await tuaStorage.clear(['steve', DEFAULT_KEY_PREFIX])

const store = AsyncStorage.getStore()

expect(store.size).toBe(2)
expect(store.get('steve')).toBe('1217')
expect(store.get(DEFAULT_KEY_PREFIX)).toBe('666')
})
})

describe('save/load/remove', () => {
describe('async methods', () => {
afterEach(() => {
cache = tuaStorage._cache = {}
AsyncStorage.clear()
})

test('never save data which is destined to expired', () => (
tuaStorage
.save({ key, data, syncParams, expires: 0 })
.then(() => {
const store = AsyncStorage.getStore()
test('never save data which is destined to expired', async () => {
await tuaStorage.save({ key, data, syncParams, expires: 0 })
const store = AsyncStorage.getStore()

expect(getObjLen(cache)).toBe(0)
expect(store.size).toBe(0)
})
))
expect(getObjLen(cache)).toBe(0)
expect(store.size).toBe(0)
})

test('load one exist item without cache', () => {
test('load one exist item without cache', async () => {
const expectedVal = getExpectedVal(data)

return tuaStorage
.save({ key, data })
.then(() => tuaStorage.load({ key, isEnableCache: false }))
.then((loadedData) => {
// load function returns rawData
expect(loadedData).toBe(data)
await tuaStorage.save({ key, data })
const loadedData = await tuaStorage.load({ key, isEnableCache: false })

// load function returns rawData
expect(loadedData).toBe(data)

const store = AsyncStorage.getStore()
const store = AsyncStorage.getStore()

// cache
expect(getObjLen(cache)).toBe(1)
expect(stringify(cache[targetKey])).toBe(expectedVal)
// cache
expect(getObjLen(cache)).toBe(1)
expect(stringify(cache[targetKey])).toBe(expectedVal)

// storage
expect(store.size).toBe(1)
expect(stringify(store.get(targetKey))).toBe(expectedVal)
})
// storage
expect(store.size).toBe(1)
expect(stringify(store.get(targetKey))).toBe(expectedVal)
})

test('remove some undefined items', () => {
test('remove some undefined items', async () => {
const expectedVal = getExpectedVal(data)
const keyArr = ['item key1', 'item key2', 'item key3']

return tuaStorage
.save({ key, data })
.then(() => tuaStorage.remove(keyArr))
.then(() => {
const store = AsyncStorage.getStore()
await tuaStorage.save({ key, data })
await tuaStorage.remove(keyArr)

// cache
expect(getObjLen(cache)).toBe(1)
expect(stringify(cache[targetKey])).toBe(expectedVal)
const store = AsyncStorage.getStore()

// storage
expect(store.size).toBe(1)
expect(stringify(store.get(targetKey))).toBe(expectedVal)
})
// cache
expect(getObjLen(cache)).toBe(1)
expect(stringify(cache[targetKey])).toBe(expectedVal)

// storage
expect(store.size).toBe(1)
expect(stringify(store.get(targetKey))).toBe(expectedVal)
})

test('get storage info', () => (
tuaStorage
.save({ key, data })
.then(tuaStorage.getInfo.bind(tuaStorage))
.then(({ keys }) => {
expect(keys).toEqual([`TUA_STORAGE_PREFIX: ${key}`])
})
))
test('get storage info', async () => {
await tuaStorage.save({ key, data })
const { keys } = await tuaStorage.getInfo()

expect(keys).toEqual([`TUA_STORAGE_PREFIX: ${key}`])
})
})

describe('error handling', () => {
Expand Down
Loading

0 comments on commit 02cfd36

Please sign in to comment.