async-selector
Advanced tools
Comparing version 1.0.6 to 1.0.7
import createAsyncSelector from '../src/index'; | ||
import _ from '../src/underscore'; | ||
const state = { | ||
@@ -9,2 +11,3 @@ text: "Ma", | ||
function getEmployees(text) { | ||
return new Promise((resolve, reject) => { | ||
@@ -48,3 +51,3 @@ setTimeout(() => { | ||
test('Test createAsyncSelector async value', () => { | ||
test('Test createAsyncSelector async value', done => { | ||
const employees = createAsyncSelector(params, state => state.text); | ||
@@ -54,3 +57,3 @@ | ||
value: ["Mark Metzger"], | ||
previous: undefined, | ||
previous: ["Mark Metzger"], | ||
isWaiting: false, | ||
@@ -62,3 +65,8 @@ isResolved: true, | ||
setTimeout(() => { | ||
expect(deepEqual(employees(state), expected)).toBe(true); | ||
try { | ||
expect(deepEqual(employees(state), expected)).toBe(true); | ||
} catch (e) { | ||
done.fail(e) | ||
} | ||
done(); | ||
}, 200) | ||
@@ -68,3 +76,3 @@ | ||
test('Test createAsyncSelector previous value', () => { | ||
test('Test createAsyncSelector previous value', done => { | ||
const employees = createAsyncSelector(params, state => state.text); | ||
@@ -74,3 +82,3 @@ | ||
value: ["Steven Miller"], | ||
previous: ["Mark Metzger"], | ||
previous: ["Steven Miller"], | ||
isWaiting: false, | ||
@@ -87,3 +95,8 @@ isResolved: true, | ||
setTimeout(() => { | ||
expect(deepEqual(employees(state), expected)).toBe(true); | ||
try { | ||
expect(deepEqual(employees(state), expected)).toBe(true); | ||
} catch (e) { | ||
done.fail(e) | ||
} | ||
done() | ||
}, 200) | ||
@@ -93,5 +106,5 @@ }, 200) | ||
test('Test createAsyncSelector rejected', () => { | ||
test('Test createAsyncSelector rejected', done => { | ||
const employees = createAsyncSelector(params, state => state.text); | ||
const state = {text: 'Mar'}; | ||
const expected = { | ||
@@ -111,3 +124,8 @@ value: "Search Text Too Long", | ||
setTimeout(() => { | ||
expect(deepEqual(employees(state), expected)).toBe(true); | ||
try { | ||
expect(deepEqual(employees(state), expected)).toBe(true); | ||
} catch (e) { | ||
done.fail(e) | ||
} | ||
done() | ||
}, 200) | ||
@@ -118,2 +136,4 @@ }, 200) | ||
test('memoization', () => { | ||
let count = 0; | ||
let state = {text: 'gg'} | ||
const sync = () => {count += 1}; | ||
@@ -163,3 +183,3 @@ const employees = createAsyncSelector({...params, sync}, state => state.text); | ||
test('cancel', () => { | ||
test('cancel', done => { | ||
const onCancel = () => {count += 1}; | ||
@@ -173,3 +193,9 @@ const employees = createAsyncSelector({...params, onCancel}, state => state.text); | ||
employees(state, true); | ||
expect(count).toBe(1); | ||
try { | ||
expect(count).toBe(1); | ||
} catch (e) { | ||
done.fail(e) | ||
} | ||
done() | ||
}, 500); | ||
@@ -194,6 +220,7 @@ }); | ||
test('onResolve', () => { | ||
test('onResolve', done => { | ||
let count = 0; | ||
const onResolve = () => {count += 1}; | ||
const employees = createAsyncSelector({...params, onResolve}, state => state.text); | ||
count = 0; | ||
employees(state); | ||
@@ -205,3 +232,8 @@ setTimeout(() => { | ||
setTimeout(() => { | ||
expect(count).toBe(1); | ||
try { | ||
expect(count).toBe(1); | ||
} catch (e) { | ||
done.fail(e) | ||
} | ||
done() | ||
}, 200); | ||
@@ -212,3 +244,4 @@ }, 200); | ||
test('onResolve', () => { | ||
test('onResolve forceUpdate', done => { | ||
let count = 0; | ||
const onResolve = () => {count += 1}; | ||
@@ -223,3 +256,8 @@ const employees = createAsyncSelector({...params, onResolve}, state => state.text); | ||
setTimeout(() => { | ||
expect(count).toBe(3); | ||
try { | ||
expect(count).toBe(3); | ||
} catch (e) { | ||
done.fail(e) | ||
} | ||
done() | ||
}, 200); | ||
@@ -230,13 +268,18 @@ }, 200); | ||
test('onResolve', () => { | ||
test('onResolve', done => { | ||
let count = 0; | ||
const onResolve = () => {count += 1}; | ||
const employees = createAsyncSelector({...params, onResolve}, state => state.text); | ||
count = 0; | ||
employees(state); | ||
setTimeout(() => { | ||
employees(state, true); | ||
employees(state); | ||
setTimeout(() => { | ||
employees(state, true); | ||
setTimeout(() => { | ||
expect(count).toBe(2); | ||
try { | ||
expect(count).toBe(2); | ||
} catch (e) { | ||
done.fail(e) | ||
} | ||
done() | ||
}, 200); | ||
@@ -247,18 +290,248 @@ }, 200); | ||
test('onResolve', () => { | ||
const onResolve = () => {count += 1}; | ||
const shouldUseAsync = (text) => text === ''; | ||
const employees = createAsyncSelector({...params, onResolve, shouldUseAsync}, state => state.text); | ||
count = 0; | ||
employees({text: 'Ma'}); | ||
test('debounce', done => { | ||
let c = 0; | ||
const throttle = f => _.debounce(f, 300); | ||
const onResolve = () => {c += 1}; | ||
const employees = createAsyncSelector({...params, onResolve, throttle}, state => state.text); | ||
employees({text: 'a'}); | ||
setTimeout(() => { | ||
employees({text: ''}); | ||
employees({text: ''}); | ||
employees({text: 'b'}); | ||
setTimeout(() => { | ||
employees(state, {text: 'Ma'}); | ||
employees({text: 'c'}); | ||
setTimeout(() => { | ||
expect(count).toBe(1); | ||
employees({text: 'd'}); | ||
setTimeout(() => { | ||
employees({text: 'e'}); | ||
setTimeout(() => { | ||
try { | ||
expect(c).toBe(1); | ||
} catch (e) { | ||
done.fail(e) | ||
} | ||
done() | ||
}, 400); | ||
}, 400); | ||
}, 200); | ||
}, 200); | ||
}, 10); | ||
}); | ||
}, 200); | ||
}); | ||
test('debounce', done => { | ||
let c = 0; | ||
const throttle = f => _.debounce(f, 300); | ||
const onResolve = () => {c += 1}; | ||
const employees = createAsyncSelector({...params, onResolve, throttle}, state => state.text); | ||
employees({text: 'a'}); | ||
setTimeout(() => { | ||
employees({text: 'b'}); | ||
setTimeout(() => { | ||
employees({text: 'c'}); | ||
setTimeout(() => { | ||
employees({text: 'd'}); | ||
setTimeout(() => { | ||
employees({text: 'e'}); | ||
setTimeout(() => { | ||
try { | ||
expect(c).toBe(3); | ||
} catch (e) { | ||
done.fail(e) | ||
} | ||
done() | ||
}, 800); | ||
}, 400); | ||
}, 400); | ||
}, 200); | ||
}, 200); | ||
}); | ||
test('throttle', done => { | ||
let c = 0; | ||
const throttle = f => _.throttle(f, 200); | ||
const onResolve = (val) => {console.log(val); c += 1;}; | ||
const employees = createAsyncSelector({...params, onResolve, throttle}, state => state.text); | ||
employees({text: 'a'}); | ||
setTimeout(() => { | ||
employees({text: 'b'}); | ||
setTimeout(() => { | ||
employees({text: 'c'}); | ||
setTimeout(() => { | ||
employees({text: 'd'}); | ||
setTimeout(() => { | ||
employees({text: 'e'}); | ||
setTimeout(() => { | ||
try { | ||
expect(c).toBe(2); | ||
} catch (e) { | ||
done.fail(e) | ||
} | ||
done() | ||
}, 60); | ||
}, 60); | ||
}, 60); | ||
}, 60); | ||
}, 60); | ||
}); | ||
test('throttle', () => { | ||
let c = 0; | ||
const state = {text: 'Ma'}; | ||
const throttle = f => _.throttle(f, 50); | ||
const onResolve = () => {c += 1}; | ||
const employees = createAsyncSelector({...params, onResolve, throttle}, state => state.text); | ||
const expected = { | ||
value: [], | ||
previous: ['Mark Metzger'], | ||
isWaiting: true, | ||
isResolved: false, | ||
isRejected: false | ||
} | ||
employees(state); | ||
setTimeout(() => { | ||
employees(state); | ||
const result = employees(state); | ||
expect(deepEqual(result, expected)).toBe(true); | ||
},200) | ||
}); | ||
test('throttle', () => { | ||
let c = 0; | ||
let state = {text: 'Ma'}; | ||
const throttle = f => _.throttle(f, 50); | ||
const onResolve = () => {c += 1}; | ||
const employees = createAsyncSelector({...params, onResolve, throttle}, state => state.text); | ||
const expected = { | ||
value: 'Search Text Too Long', | ||
previous: ['Mark Metzger'], | ||
isWaiting: false, | ||
isResolved: false, | ||
isRejected: true, | ||
} | ||
employees(state); | ||
setTimeout(() => { | ||
state = {text: 'aaaaaaaaaaaaaa'}; | ||
employees(state); | ||
setTimeout(() => { | ||
const result = employees(state); | ||
expect(deepEqual(result, expected)).toBe(true); | ||
}, 500); | ||
},200) | ||
}); | ||
test('throttle memoization', () => { | ||
let c = 0; | ||
let state = {text: 'Ma'}; | ||
const throttle = f => _.throttle(f, 50); | ||
const onResolve = () => {c += 1}; | ||
const employees = createAsyncSelector({...params, onResolve, throttle}, state => state.text); | ||
const expected = { | ||
value: 'Search Text Too Long', | ||
previous: ['Mark Metzger'], | ||
isWaiting: false, | ||
isResolved: false, | ||
isRejected: true, | ||
} | ||
employees(state); | ||
employees(state); | ||
employees(state); | ||
employees(state); | ||
setTimeout(() => { | ||
state = {text: 'aaaaaaaaaaaaaa'}; | ||
employees(state); | ||
setTimeout(() => { | ||
const result = employees(state); | ||
expect(c).toBe(1); | ||
}, 500); | ||
},200) | ||
}); | ||
function getAges(employees, maxAge) { | ||
return new Promise((resolve, reject) => { | ||
setTimeout(() => { | ||
const database = ["Mark Metzger", "Steven Miller"]; | ||
const ages = [12, 34]; | ||
if (text.length > 10) { | ||
reject('Search Text Too Long'); | ||
} else { | ||
const employeeAges = employees.map(name => { | ||
return ages[database.indexOf(name)] | ||
}); | ||
resolve(employeeAges.filter(age => age <= maxAge)); | ||
} | ||
}, 100); | ||
}); | ||
} | ||
const params2 = { | ||
sync:(employees, ages) => [], | ||
async: getAges, | ||
} | ||
test('multiple params', () => { | ||
let c = 0; | ||
let state = {employees: ['Mark Metzger'], maxAge: 40}; | ||
const ages = createAsyncSelector(params2, s => s.employees, s => s.maxAge); | ||
const result = ages(state); | ||
const expected = { | ||
value: [], | ||
previous: undefined, | ||
isWaiting: true, | ||
isResolved: false, | ||
isRejected: false, | ||
} | ||
expect(deepEqual(result, expected)).toBe(true); | ||
}); | ||
test('multiple params2', () => { | ||
let c = 0; | ||
let state = {employees: ['Mark Metzger'], maxAge: 40}; | ||
const ages = createAsyncSelector(params2, s => s.employees, s => s.maxAge); | ||
const expected = { | ||
value: [12], | ||
previous: undefined, | ||
isWaiting: false, | ||
isResolved: true, | ||
isRejected: false, | ||
} | ||
ages(state); | ||
setTimeout(() => { | ||
console.log(expected); | ||
const result = ages(state); | ||
console.log('blahhhhh', result); | ||
expect(deepEqual(result, expected)).toBe(true); | ||
}, 300); | ||
}); | ||
test('multiple params3', () => { | ||
let c = 0; | ||
let state = {employees: ['Mark Metzger'], maxAge: 10}; | ||
const ages = createAsyncSelector(params2, s => s.employees, s => s.maxAge); | ||
const result = ages(state); | ||
const expected = { | ||
value: [], | ||
previous: undefined, | ||
isWaiting: false, | ||
isResolved: true, | ||
isRejected: false, | ||
} | ||
ages(state); | ||
setTimeout(() => { | ||
const result = ages(state); | ||
expect(deepEqual(result, expected)).toBe(true); | ||
done(); | ||
}); | ||
}); |
@@ -55,3 +55,4 @@ 'use strict'; | ||
shouldUseAsync = params.shouldUseAsync, | ||
omitStatus = params.omitStatus; | ||
omitStatus = params.omitStatus, | ||
throttle = params.throttle; | ||
@@ -65,2 +66,3 @@ onReject = typeof onReject === 'function' ? onReject : emptyFunction; | ||
omitStatus = omitStatus === undefined ? false : omitStatus; | ||
throttle = typeof throttle === 'function' ? throttle : null; | ||
@@ -72,5 +74,7 @@ //selector state | ||
var previousResolution = undefined; | ||
var f = null; | ||
var func = function func(state) { | ||
var forceUpdate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
var internal = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; | ||
@@ -81,3 +85,18 @@ var mapped = selectors.map(function (f) { | ||
var changed = forceUpdate || hasChanged(oldInputs, mapped); | ||
//console.log(changed, mapped, internal) | ||
if (changed) { | ||
/* Handle throttling / debouncing if required */ | ||
if (throttle !== null && f === null) { | ||
f = throttle(function (state, forceUpdate) { | ||
return func(state, forceUpdate, true); | ||
}); | ||
} | ||
if (f !== null && internal === false) { | ||
f(state, forceUpdate); | ||
memoizedResult = createResultObject(sync(mapped), previousResolution, true, false, false, omitStatus); | ||
return memoizedResult; | ||
} | ||
/* //////////////////////////////////////////// */ | ||
if (isPromisePending) { | ||
@@ -88,3 +107,3 @@ onCancel.apply(undefined, [promise].concat(_toConsumableArray(oldInputs))); | ||
memoizedResult = createResultObject(sync(mapped), previousResolution, true, false, false, omitStatus); | ||
memoizedResult = createResultObject(sync.apply(undefined, _toConsumableArray(mapped)), previousResolution, true, false, false, omitStatus); | ||
@@ -94,5 +113,6 @@ if (!shouldUseAsync.apply(undefined, _toConsumableArray(mapped))) { | ||
} | ||
var promise = params.async(mapped); | ||
var promise = params.async.apply(params, _toConsumableArray(mapped)); | ||
isPromisePending = true; | ||
promise.then(function (promiseResolution) { | ||
//console.log('resolution', promiseResolution, hasChanged(oldInputs, mapped)) | ||
if (!hasChanged(oldInputs, mapped)) { | ||
@@ -99,0 +119,0 @@ previousResolution = promiseResolution; |
{ | ||
"name": "async-selector", | ||
"version": "1.0.6", | ||
"version": "1.0.7", | ||
"description": "Select values from databases using asynchronous selectors.", | ||
@@ -23,3 +23,3 @@ "main": "./dist/index.js", | ||
], | ||
"author": "Mark Metgzer markmetzger@utexas.edu", | ||
"author": "Mark Metzger markmetzger@utexas.edu", | ||
"license": "MIT", | ||
@@ -38,3 +38,4 @@ "bugs": { | ||
"coveralls": "^2.13.1", | ||
"jest-cli": "^20.0.4" | ||
"jest-cli": "^20.0.4", | ||
"underscore": "^1.9.0" | ||
}, | ||
@@ -41,0 +42,0 @@ "jest": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
135458
10
668
8