js-코루틴을 사용하여 TypeScript에서 글리치 없는 1,000,000 레코드 데이터 처리
30006 단어 webdevtypescriptreactjavascript
검색이 계속됨에 따라 계속 입력하고 레코드 탐색을 시작할 수 있는 방법에 주목하십시오. 이는 메인 스레드에서 협업 멀티태스킹을 사용하여 수행됩니다.
이 창을 확대하면 Recharts에서 제공하는 툴팁이 제대로 작동하지 않습니다. 전체 화면 버전 보기
이 데모는 "싱글톤"함수를 정의할 수 있는 js-coroutines의 새로운 기능을 사용합니다. Singleton 함수는 이전 실행이 아직 진행 중인 경우 자동으로 취소하고 다시 시작합니다. 이것이 바로 이와 같은 검색에 필요한 것입니다.
const process = singleton(function*(resolve: Function, search: string, sortColumn: string) {
let yieldCounter = 0
if (!search.trim() && !sortColumn?.trim()) {
resolve({ data, searching: false })
addCharts(data)
return
}
resolve({ searching: true, data: [] })
let parts = search.toLowerCase().split(" ")
let i = 0
let progress = 0
let output : Data[] = []
for (let record of data) {
if (
parts.every(p =>
record.description
.split(" ")
.some(v => v.toLowerCase().startsWith(p))
)
) {
output.push(record)
if (output.length === 250) {
resolve({data: output})
yield sortAsync(output, (v : Data)=>v[sortColumn])
}
}
let nextProgress = ((i++ / data.length) * 100) | 0
if (nextProgress !== progress) resolve({ progress: nextProgress })
progress = nextProgress
yield* check()
}
resolve({sorting: true})
yield sortAsync(output, (v : Data)=>v[sortColumn])
resolve({sorting: false})
resolve({ searching: false, data: output })
addCharts(output)
function* check(fn?: Function) {
yieldCounter++
if ((yieldCounter & 127) === 0) {
if (fn) fn()
yield
}
}
}, {})
이 루틴은 우리가 무언가를 찾고 있는지 확인하는 것으로 시작하고 그렇지 않은 경우 더 빠른 경로를 택합니다.
검색 중이라고 가정하면 진행 상황을 업데이트하기 위해 값을 여러 번 해결하는 깔끔한 트릭을 사용합니다. 이를 통해 250개의 레코드가 있는 즉시 결과를 표시하고 1%마다 진행률을 업데이트한 다음 검색 및 정렬 표시기를 켜고 끌 수 있습니다.
resolve를 호출하면 검색이 진행되는 동안 모든 것이 원활하게 업데이트되도록 UI를 다시 그리는 표준 React.useState()에 일부 데이터가 병합됩니다.
interface Components {
data?: Array<Data>
searching?: boolean
progress?: number,
sorting?: boolean,
charts?: []
}
function UI(): JSX.Element {
const [search, setSearch] = React.useState("")
const [sortColumn, setSortColumn] = React.useState('')
const [components, setComponents] = React.useState<Components>({})
React.useEffect(() => {
setComponents({ searching: true })
// Call the singleton to process
process(merge, search, sortColumn)
}, [search, sortColumn])
return (
<Grid container spacing={2}>
<Grid item xs={12}>
<TextField
fullWidth
helperText="Search for names, colors, animals or countries. Separate words with spaces."
InputProps={{
endAdornment: components.searching ? (
<CircularProgress color="primary" size={"1em"} />
) : null
}}
variant="outlined"
value={search}
onChange={handleSetSearch}
label="Search"
/>
</Grid>
<Grid item xs={12} style={{visibility: components.searching ? 'visible' : 'hidden'}}>
<LinearProgress
variant={components.sorting ? "indeterminate": "determinate"}
value={components.progress || 0}
color="secondary"
/>
</Grid>
<Grid item xs={12}>
<RecordView sortColumn={sortColumn} onSetSortColumn={setSortColumn} records={components.data} />
</Grid>
{components.charts}
</Grid>
)
function merge(update: Components): void {
setComponents((prev: Components) => ({ ...prev, ...update }))
}
function handleSetSearch(event: React.ChangeEvent<HTMLInputElement>) {
setSearch(event.currentTarget.value)
}
}
merge
함수는 루틴이 진행됨에 따라 항목을 업데이트하는 작업을 수행하며 "싱글톤"함수를 정의했으므로 검색 또는 정렬 속성이 변경될 때마다 자동으로 중지되고 다시 시작됩니다.차트는 각각 개별적으로 계산을 시작하고 기본 프로세스를 다시 시작하면 차트도 다시 시작되도록 실행을 기본 프로세스에 "결합"합니다.
function Chart({data, column, children, cols} : {cols?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12, data: Array<Data>, column: (row: any)=>string, children?: any}) {
const [chartData, setData] = React.useState()
React.useEffect(()=>{
const promise = run(count(data, column))
// Link the lifetime of the count function to the
// main process singleton
process.join(promise).then((result: any)=>setData(result))
}, [data, column])
return <Grid item xs={cols || 6}>
{!chartData ? <CircularProgress/> : <ResponsiveContainer width='100%' height={200}>
<BarChart data={chartData}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis />
<Tooltip />
<Bar dataKey="value" fill="#8884d8">
{children ? children(chartData) : null}
</Bar>
</BarChart>
</ResponsiveContainer>}
</Grid>
}
여기에서는 헬퍼 Async 함수와 생성기를 혼합하여 사용하여 최대한 제어할 수 있습니다. 마지막으로 남은 관심 생성기는 차트 결과를 계산하는 생성기입니다.
function * count(data: Data[], column: (row: Data)=>string, forceLabelSort?: boolean) : Generator<any, Array<ChartData>, any> {
const results = yield reduceAsync(data, (accumulator: any, d: Data)=>{
const value = column(d)
accumulator[value] = (accumulator[value] || 0) + 1
return accumulator
}, {})
let output : Array<ChartData> = []
yield forEachAsync(results, (value: number, key: string)=>{
key && output.push({name: key, value})
})
if(output.length > 20 && !forceLabelSort) {
yield sortAsync(output, (v:ChartData)=>-v.value)
} else {
yield sortAsync(output, (v:ChartData)=>v.name)
}
return output
}
이것은 단순히 함수에 의해 추출된 레이블을 세고 결과를 적절하게 정렬합니다.
Reference
이 문제에 관하여(js-코루틴을 사용하여 TypeScript에서 글리치 없는 1,000,000 레코드 데이터 처리), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/miketalbot/glitch-free-1-000-000-record-data-processing-in-typescript-with-js-coroutines-fmp텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)