Привязка внешних API к шаблону может быть решена с помощью классического экземпляра шаблона '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 обычно нереактивный, вызывая триггер от autorun
до , а не снова, если данные во внешнем API изменились.Если источником будет коллекция Mongo, внутренний Tracker шаблона автоматически перезапустится и обновит ваше состояние 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
}
})
Плюсы
- Простота реализации
- Мелкозернистая настройка времени для беглого опыта
Минусы
- setInterval - это раковина
- вы должны очистить его, чтобы предотвратить утечки памяти (в onDestroyed)
Трудный путь: позвольте службе внешнего API звонить вам!
Если у вас есть возможность разрешить подключаться внешней службе и вызывать ваше приложение через 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})
}
})
Теперь на клиенте вам просто нужно подписаться на данныеи обновите реактивную переменную автоматически:
клиент:
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({})
}
})
Внешняя служба / приложение:
// 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})
}
Плюсы:
- Шаблон автоматически обновляется при обновлении коллекции
- Нет таймеров = нет приемников!
- Не требуется никаких дополнительных реактивных переменных
- Вы можете использоватьколлекция, чтобы сделать внешние данные постоянными, кэшировать их или создать ревизию / историю
- Вы можете подключать / отключать внешние службы (лучшее масштабирование, меньше зависимостей)
Минусы:
- Высокая кривая обучения (но это стоит усилий)
- Работает, только если у вас есть контроль над внешней службой
- Больше кода = больше потенциальных ошибок, поэтому больше тестов для записи