我有以下情况:
我有以下模板:
<ul>
{{#each persons}}
{{Name}}
{{/each}}
</ul>
模板.js文件中的persons = ReactiveVar([])
。
我正在更新HTTP Rest API的回调中的persons变量:
var instance = Template.instance();
API(url, (error, result) = instance.persons.set(result)) //result is an array
UI上没有任何反应。我怎样才能解决这个问题? (我也愿意使用简单的数组,但是条件是从API回调中填充数组)。
答案 0 :(得分:0)
将外部API绑定到模板可以通过经典的Template实例的ReactiveVar / ReactiveDict(让我们将它们称为反应性源)来解决。请注意,您不应在帮助程序中对事件源进行这些调用或更新,而应在事件内或onCreated内进行。
让我们来看看您的模板:
<ul>
{{#each persons}}
{{Name}}
{{/each}}
</ul>
然后我们在onCreated函数中进行调用:
Template.myTemplate.onCreated(function () {
const instance = this
instance.state = new ReactiveDict()
instance.state.set('persons', [])
// Template's internal tracker
instance.autorun(() => {
API(url, (error, result) => instance.state.set('persons', result)) //result is an array
})
})
并且仅通过助手中的反应性源返回数据:
Template.myTemplate.helpers({
persons() {
return Template.instance().state.get('persons')
}
})
现在,这带来了另一个问题:外部API通常不响应,如果外部API中的数据已更改,则autorun
会再次不触发。如果源是Mongo集合,则模板的内部跟踪器将自动重新运行并更新您的persons
状态。
如果您只想获取一次外部数据,那很好。但是,为了scan
进行更改的外部api,您有一些不同的选择:
简便方法:使用计时器(setInterval):
let timerId
Template.myTemplate.onCreated(function () {
const instance = this
instance.state = new ReactiveDict()
instance.state.set('persons', [])
timerId = setInterval(() => {
API(url, (error, result) => instance.state.set('persons', result)) //result is an array
}, 5000) // scans each 5 seconds for updates
})
Template.myTemplate.onDestroyed(function () {
if (timerId) {
clearInterval(timerId)
timerId = null
}
})
专业人士
缺点
方法:让外部API的服务呼叫您!
如果您可以选择让外部服务connect and call your app via ddp,则可以让外部服务决定何时更改数据并准备启动数据,以便您当前的应用可以自动更新。
您需要一个方法和一个集合:
服务器和客户端:
export const ExternalData = new Mongo.Collection('externalData')
服务器:
import ExternalData from 'path/to/externalData'
Meteor.methods({
'myApp.updateExternalData'(args) {
// check permissions...
// check data integrity...
const {url} = args
const {data} = args
ExternalData.update({url}, {$set: data})
}
})
Meteor.publish({
'myApp.externalData'(url) {
return ExternalData.find({url})
}
})
现在,在客户端上,您只需要订阅数据并自动更新反应式var:
客户端:
import ExternalData from 'path/to/externalData'
Template.myTemplate.onCreated(function () {
const instance = this
// subscribe to changes
instance.autorun(() => {
const subscription = this.subscribe('myApp.externalData', url)
if (subscription.ready()) {
console.log('myApp.externalData is ready')
}
})
})
Template.myTemplate.helpers({
persons() {
return ExternalData.find({})
}
})
外部服务/ APP:
// if the external app is a meteor app you are lucky and can go with:
// https://docs.meteor.com/api/connections.html#DDP-connect
// Otherwise you can use the npm package:
// https://www.npmjs.com/package/ddp
// For authentication you can use:
// https://github.com/reactioncommerce/meteor-ddp-login
// or
// https://www.npmjs.com/package/ddp-login
const connection = // create a ddp connection
function onDataChanged () {
const data = //... get data from the backend of your ext. servie
const url = //... and the url for which the data is relevant
// call the app to update the data:
connection.call('myApp.updateExternalData', {url, data})
}
优点:
缺点: