Browse Source

make_model: be lazy and correct on multiple entrances

master
Bing Sun 5 years ago
parent
commit
e69cc33ecd
Signed by: sunb GPG Key ID: F7795F8C590626AB
1 changed files with 43 additions and 31 deletions
  1. +43
    -31
      src/util/make_model.js

+ 43
- 31
src/util/make_model.js View File

@@ -40,8 +40,9 @@ export default (options={}) => {
upstream_limit: null upstream_limit: null
} }


// some random places to make things work
// some random variables to make things work
let _xhr = null let _xhr = null
let _promise = null


// construct the model // construct the model
return { return {
@@ -58,14 +59,20 @@ export default (options={}) => {
if (limit == Infinity) if (limit == Infinity)
limit = _cache.upstream_limit || _cache.count || Infinity limit = _cache.upstream_limit || _cache.count || Infinity


// be lazy: if the data is presented, return the value immediately
// be lazy 1: if the data is presented, return the value immediately
// //
// note that Array.every(list) == true if list is empty // note that Array.every(list) == true if list is empty
if (_cache.data.slice(offset, offset+limit).length > 0 && _cache.data.slice(offset, offset+limit).every(data => data != undefined))
return Promise.resolve(_cache.data.slice(offset, offset+limit))
let _portion = _cache.data.slice(offset, offset+limit)
if (_portion.length > 0 && _portion.every(data => data != undefined))
return Promise.resolve(_portion)

// be lazy 2: if there is a promise, return it if ambient matches or
// cancel it
if (_promise != null)
return _promise


// now the hard work // now the hard work
return _configs.api.request({
_promise = _configs.api.request({
method: 'GET', method: 'GET',
url: _configs.endpoint, url: _configs.endpoint,
headers: _cache.count == null ? { headers: _cache.count == null ? {
@@ -76,34 +83,39 @@ export default (options={}) => {
// transform model state to postgest queries // transform model state to postgest queries
//...ambient_queries, //...ambient_queries,
offset == 0 ? undefined : {label: 'offset', value: offset}, offset == 0 ? undefined : {label: 'offset', value: offset},
limit == Infinity ? undefined : {label: 'limit', value: limit}
]
}).then(response => {
// gather begin/end/count
let [_range, _count] = _xhr.getResponseHeader('content-range').split('/')
let [_begin, _end] = _range.split('-').map(v => ~~v)

// update count if presented
if (_count != '*') _cache.count = _count

// see if an upstream limit is exposed
if (_end - _begin + 1 < limit) _cache.upstream_limit = _end - _begin + 1

// fill the data cache
response.forEach((data, i) => {
// _value_filters.forEach(([label, config]) => data[config.alias || label] = config.value_filter(data[config.alias || label]))
_cache.data[_begin + i] = data
limit == Infinity ? undefined : {label: 'limit', value: limit}
]
}).then(response => {
// gather begin/end/count
let [_range, _count] = _xhr.getResponseHeader('content-range').split('/')
let [_begin, _end] = _range.split('-').map(v => ~~v)

// update count if presented
if (_count != '*') _cache.count = _count

// see if an upstream limit is exposed
if (_end - _begin + 1 < limit) _cache.upstream_limit = _end - _begin + 1

// fill the data cache
response.forEach((data, i) => {
// _value_filters.forEach(([label, config]) => data[config.alias || label] = config.value_filter(data[config.alias || label]))
_cache.data[_begin + i] = data
})

// assert offset/limit and returned range
if (offset != _begin || _end - _begin + 1 > limit)
throw 'The request and response data range mismatches!'
if (_end - _begin + 1 < limit)
console.warn('The response range is narrower than requested, probably due to an upstream hard limit.')

// clean model state
_promise = null

// return data
return _cache.data.slice(_begin, _end + 1)
}) })


// assert offset/limit and returned range
if (offset != _begin || _end - _begin + 1 > limit)
throw 'The request and response data range mismatches!'
if (_end - _begin + 1 < limit)
console.warn('The response range is narrower than requested, probably due to an upstream hard limit.')

// return
return _cache.data.slice(_begin, _end + 1)
})
return _promise
} }
} }
} }


Loading…
Cancel
Save