javascript - 如何等到流星订阅数据完全完成?
问题描述
我一直在查看很多问题/答案以及流星文档,但仍然遇到流星反应问题并等待订阅数据完全加载。我正在尝试做两件不同的事情,一件是如果从数据库收到的数组小于在客户端创建的数组,然后做其他事情,如果它更大或相等。
问题出在我的订阅上,数据有时会通过管道传输,所以第一条语句总是至少触发一次。
我想知道在调用函数之前是否有办法确保数据库中的所有数据都已通过。
if (import.length < arrayLength) {
...
}
if (import.length > arrayLength || import.length === arrayLength) {
...
}
下面的完整代码示例
import { DropzoneDialog } from "material-ui-dropzone";
import React, { useState, useEffect, useRef } from "react";
import Button from "@material-ui/core/Button";
import { Cards } from "../../../../both/collections";
import { withTracker } from "meteor/react-meteor-data";
import { makeStyles } from "@material-ui/core/styles";
import { Meteor } from 'meteor/meteor';
import _, { map, object } from 'underscore';
const useStyles = makeStyles({
importButton: {
color: "#C8C8C8",
borderColor: "#C8C8C8",
"&:hover": {
backgroundColor: "rgba(72,72,72,0.7)",
borderColor: "rgba(255, 255, 255)",
color: "rgba(255, 255, 255)",
},
},
});
function importDeck(files, setDeckIsReady, setDeckLength, setCountObj, sub, setSubscription) {
let reader = new FileReader();
reader.readAsText(files[0]);
reader.onload = function () {
let cardArray = reader.result.split("\n");
let cardArrayFiltered = cardArray.filter(Boolean)
const countObj = cardArrayFiltered.reduce((acc, next) => {
count = next.substr(0, next.indexOf(' '));
name = next.substr(next.indexOf(' ') + 1);
return {...acc, [name]: count}
}, {});
sub.stop()
const subscription = Meteor.subscribe('cardSearchTwo', Object.keys(countObj), {onReady() {setDeckIsReady(true)}})
setDeckLength(Object.keys(countObj).length)
setCountObj(countObj)
setSubscription(subscription)
};
}
export function DeckImport({importCards, setCurrentDeck, importDeckFinal, search, setSearch}) {
const classes = useStyles()
const [open, setOpen] = useState(false);
const [deckIsReady, setDeckIsReady] = useState(false);
const [deckLength, setDeckLength] = useState(0);
const [countObj, setCountObj] = useState({});
const [subscription, setSubscription] = useState({stop(){}})
const [isReady, setIsReady] = useState(false)
console.log(deckIsReady, importCards)
let missingCards = []
let fixedDeck = importCards
useEffect(() => {
if (importCards.length < deckLength && deckIsReady) {
fixedDeck = []
Object.keys(countObj).forEach(card => {
if (!importCards.some(e => e.name === card)) missingCards.push(card)
})
fixedDeck = importCards.filter(card => !missingCards.includes(card.name))
console.log('LESS THAN', fixedDeck.length, missingCards.length)
importDeckFinal(fixedDeck, setCurrentDeck, countObj)
setDeckIsReady(false)
setDeckLength(0)
setCountObj({})
}
if ((importCards.length > deckLength || importCards.length === deckLength) && deckIsReady) {
fixedDeck = []
importCards.forEach(card => {
if (card.name in countObj) fixedDeck.push(card)
})
console.log('EQUAL', fixedDeck);
importDeckFinal(fixedDeck, setCurrentDeck, countObj)
setDeckIsReady(false)
setDeckLength(0)
setCountObj({})
}
})
return (
<div>
<Button
variant="outlined"
color="primary"
component="label"
onClick={() => setOpen(true)}
className={classes.importButton}>
Import
</Button>
<DropzoneDialog
acceptedFiles={["text/*"]}
cancelButtonText={"cancel"}
submitButtonText={"submit"}
maxFileSize={5000000}
open={open}
onClose={() => setOpen(false)}
onSave={(files) => {
importDeck(
files,
setDeckIsReady,
setDeckLength,
setCountObj,
subscription,
setSubscription,
setIsReady
);
setOpen(false);
}}
showPreviews={true}
showFileNamesInPreview={true}
/>
</div>
)
}
export default withTracker(props => {
const cards = Cards.find({}, { sort: {name: 1}}).fetch();
const uniqueNames = _.uniq(cards.map(function(x) {return x.name;}), true)
return {
importCards: uniqueNames.map(name => cards.find(({ name: cName }) => cName === name))
};
})(DeckImport);
具体来说,deckIsReady 被设置为 True 当只有一部分数据完全准备好时。
解决方案
你可以使用两件事
useTracker
React 钩子是meteor-react-data
. 每当响应式数据源更改时,此挂钩就会重新运行。使用
Subscription.ready()
来确定数据源是否已准备好使用。
把它放在一起,比如:
const importReady = useTracker(() => Meteor.subscribe('cardSearchTwo').ready())
推荐阅读
- c++ - 如何使用按钮更新 GTK3 图像以使用 C++ 从相机捕获图片
- networking - 我在wireshark上有一个小项目,我有点卡住了
- react-native - 如何启用新的 LogBox (RN)
- angular - IE11 和 Angular 问题 - 错误类型错误:对象不支持此操作
- swift - 当我使用“node.physicsBody.velocity”时,我可以在 SCNScene 中获得 SCNNode 位置吗?
- excel - 如何使用 Text-To-Columns 格式化为文本
- r - R tmap sf错误:查看地图时参数暗示不同的行数
- swift - How to implement Recursive Paginated Network Call using RxSwift
- python - 无法在 vscode 中导入自定义 python 模块
- r - 从一个df绘制点,从另一个绘制误差条