I have this helper which calls ImageResolver.js to resize images, but it’s not working because resolver return async. I think I need to use a reactiveVar to maintain the template instance or something, but nothing I’ve tried has worked.
getImage: function(url) {
resolver.resolve(url, function(result) {
if (result) {
console.log(result.image);
return result.image;
}
});
}
});
My function is not a server-side call. it runs in the client. I’d have cross-site scripting issues if I tried to port it to a meteor.method
Oh, ok… so you could declare ReactiveVar in Template onCreated(onRendered) and then store the method result in it. It should work. What is the problem with this approach?
I’m not sure but I just get errors
Error: Exception in template helper:
TypeError: Cannot read property 'set' of undefined
Template.discover.onCreated(function(){
this.imageResolverRequests = new ReactiveVar;
});
Template.discover.helpers({
getImage: function(url) {
console.log("page:" + url);
url = Helpers.addHttp(url);
var result;
this.imageResolverRequests.set(result.image);
resolver.resolve(url, function(result) {
if (result) {
console.log(result.image);
return Template.instance().imageResolverRequests.get();
} else {
console.log("No image found");
return '';
}
});
},
How to get the result after I store it? should I put the whole helper function in the reactivevar?
Template.instance().imageResolverRequests.set(result.image);
In a helper, this
is the data context, not the template instance
Thanks, I changed this
and tried this code but I get new errors
Template.discover.helpers({
getImage: function(url) {
console.log("page:" + url);
url = Helpers.addHttp(url);
var result;
Template.instance().imageResolverRequests.set(result);
resolver.resolve(url, function(result) {
if (result) {
console.log(result.image);
var res = Template.instance().imageResolverRequests.get();
return res.image;
} else {
console.log("No image found");
return '';
}
});
},
Error: Cannot read property 'imageResolverRequests' of null
TypeError: Cannot read property 'imageResolverRequests' of null
at helpers.js?0a6261ab33124edc5a3198af4665deef5c0f08d9:21
should be this.imageResolverRequests = new ReactiveVar();
(with parentheses - and maybe an initial value): http://docs.meteor.com/#/full/reactivevar
1 Like
Template.discover.helpers({
getImage: function(url) {
console.log("page:" + url);
url = Helpers.addHttp(url);
//var result;
resolver.resolve(url, function(result) {
if (result) {
console.log(result.image);
/*//// set the reactiveVar in the callback (when it arrives) */
Template.instance().imageResolverRequests.set(result.image);
} else {
console.log("No image found");
return '';
}
});
// return the image into your template (when it gets updated)
return Template.instance().imageResolverRequests.get();
},
Thanks guys, but still no cigar
Error: Cannot read property 'imageResolverRequests' of null
TypeError: Cannot read property 'imageResolverRequests' of null
using this declaration now
Template.discover.onCreated(function() {
this.imageResolverRequests = new ReactiveVar();
});
Do I need to use Promise to make this work?
null
is returned by Template.instance()
when it can’t determine the current helper (amongst other reasons), so I wonder if this might work:
Template.discover.helpers({
getImage: function(url) {
var instance = Template.instance();
console.log("page:" + url);
url = Helpers.addHttp(url);
//var result;
resolver.resolve(url, function(result) {
if (result) {
console.log(result.image);
/*//// set the reactiveVar in the callback (when it arrives) */
instance.imageResolverRequests.set(result.image);
} else {
console.log("No image found");
return '';
}
});
// return the image into your template (when it gets updated)
return instance.imageResolverRequests.get();
},
as well @robfallows ’ suggestion, above
it might also be worth declaring the reactive var with null value
Template.discover.onCreated(function() {
this.imageResolverRequests = new ReactiveVar(null);
});
HI @robfallows
Thats interesting! On the positive side, it’s the first time I got results back! But on the negative side, it seems to spawn an infinite loop! It’s still running after a full 5 minutes. I’m only trying passing it 12 urls.
Ah maybe after I get the result I should destroy the reactVar? I’ll try that.
shock
November 9, 2015, 4:58pm
15
this should be in helper
The whole setting and checking should be part of something else - event handler or autorun in onCreated.
And yes - setting reactive var in async callback and still using it in same helpers as .get() is effective infinite loop
2 Likes
Good news that the image grabber works.
the infite loop is a tracker issue, everytime it changes, it calls the helper, and the helper is calling the list of urls, and the url is pulled and the helper is called and …
need to break out the logic somewhere
Correct - and that’s how I’ve done it before (in onCreated)! My brain must be elsewhere today.
@robfallows ’s .set and .get are both inside the helper
getImage: function(url) {
var instance = Template.instance();
//console.log("page:" + url);
url = Helpers.addHttp(url);
//var result;
resolver.resolve(url, function(result) {
if (result) {
//console.log(result.image);
/*//// set the reactiveVar in the callback (when it arrives) */
instance.imageResolverRequests.set(result.image);
} else {
console.log("No image found");
return '';
}
});
// return the image into your template (when it gets updated)
return instance.imageResolverRequests.get();
},
but yeah, now how to deal with the infinite loop. I thought this might work, but when I try it, i get no images at all
var imgUrl = instance.imageResolverRequests.get();
instance.imageResolverRequests.set(undefined);
return imgUrl;
@shock is correct - putting the set
in the helper will cause reactive runaway ™. The setting needs to be outside of the helper - in onCreated
is a good place, or in an event if you’re kicking things off from a click.
it’s the whole of this
var instance = Template.instance();
//console.log("page:" + url);
url = Helpers.addHttp(url);
//var result;
resolver.resolve(url, function(result) {
if (result) {
//console.log(result.image);
/*//// set the reactiveVar in the callback (when it arrives) */
instance.imageResolverRequests.set(result.image);
} else {
console.log("No image found");
return '';
}
});
perhaps in onRendered