Unresolved property variable when returned from method - javascript

...
doChunk().then(function (results) {
angular.forEach(results, function (info) {
if (info.data.fields.worklog) {
configProcess.results.push(info.data);
...
The above is just a sample from my AngularJS application, but it's the same issue for all data (and vanilla JS) that's returned from somewhere else - like an HTTP request in this case.
results - is the result of an HTTP request and contains an array of objects.
So when I loop over this array I access different properties of these objects.
All is fine and it works, but how can I declare what the different properties of these methods are?
Basically what I want is to get rid of code inspection errors from WebStorm like these: Unresolved variable fields at line 106.
It makes perfect sense to me why it's reported, but how do I address it?

I can suggest using JSDoc to document such objects received by ajax calls. See How to fight tons of unresolved variables warning in Webstorm?, for example

Related

Meteorjs: HTTP.get is retrieving data but isn't returning anything to the helper function variable

I have the following code that reads a json file:
Meteor.methods({
getPlaces: function(){
return HTTP.get(Meteor.absoluteUrl("/places.json"), function(e, r) {
console.log(r.data);
return r.data;
});
}
})
The console shows that its retrieving the data just fine.
Here is the part of my helper function for the template I want to display 'Places' in:
testing: function(){
return Meteor.call("getPlaces");
}
& here is my loop in the template where it is supposed to show:
{{#each testing}}
<li>{{testing.name}}</li>
{{/each}}
But it seems like I'm not calling the function right as the loop doesn't show anything. I've tested the loop by giving it random data which it works fine with but whenever I call Meteor.call or even HTTP.get directly on 'testing' it doesn't give me anything.
There are two essential problems here:
You're using HTTP.get asynchronously when you don't need to.
You're trying to use Meteor.call synchronously when you can't as it won't work like that.
Explanation of 1:
In supplying a callback to HTTP.get, you're telling Meteor to allow code execution to continue beyond that line, and pass the result of the call to the callback function. As a result, the actual method function finishes execution and will return undefined (which will be passed back to the calling function as null via EJSON) well before your actual HTTP call has returned. When that happens, the result will be logged, but even though you're returning the results in the callback, the enclosing method function won't care as it will have completed execution long before.
There are several ways to deal with this, the simplest being: don't pass a callback. On the server, you can use HTTP.get synchronously by not passing a callback, in which case code will cease executing until the results come back, and they will actually be returned to the client. Note that you cannot do this if you use HTTP.get on the client. Other ways of dealing with this involve Futures or Promises (better), but are unnecessary here.
Explanation of 2:
This is more complicated to resolve, but is fundamental to Meteor and Javascript. If you're calling an asynchronous function and you want to use the result, you need to supply a callback (or use promises). You can't just expect it to work inline for the same reasons given above. So some changes need to be made:
Don't call a method from within a template helper. You've no idea how often the template helper will run (it depends on all sorts of reactive things), so this is an essentially unbounded amount of traffic on the websocket that you're committing to. Call them when something happens (template is rendered, event handler, a specific piece of data changes (i.e. within an autorun block)), but not in a helper function.
Store the result in a reactive data source, otherwise even if you successfully receive it and put it somewhere, your UI won't update with the results.
So:
Template.yourTemplate.onCreated(function () {
this.places = new ReactiveVar()
Meteor.call("getPlaces", (err, res) => {
// do some error handling here
this.places.set(res)
})
})
{{#each Template.instance.places.get}}
<li>{{name}}</li>
{{/each}}
A few notes:
You need to install the reactive-var package, which inexplicably isn't provided out of the box, for this to work: meteor add reactive-var.
You could return the data via a template helper which uses Template.instance().places.get(), but you can just do it in-line in the template, which seems easier to me.
If the result of the first method call aren't sufficient and you need to update the results, do this in an event handler, or an autorun block as required. If the server needs to be able to push data directly to the client rather than waiting for requests for an update, then methods are the wrong tool - you need to be using Meteor's pub/sub model.

looping through key/value pair of promises in protractor

I am using protractor to test a series of webpages (actually mostly one webpage of Angular design, but others as well). I have created a series of page objects to handle this. To minimize code maintenance I have created an object with key value pairs like so:
var object = {
pageLogo: element(by.id('logo')),
searchBar: element.all(by.className('searchThing')),
...
};
The assumption being that I will only need to add something to the object to make it usable everywhere in the page object file. Of course, the file has functions (assuming you are not familiar with the page object pattern) as such:
var pageNamePageObject = function () {
var object = {...}; //list of elements
this.get = function() {
brower.get('#/someWebTag');
}
this.getElementText = function(someName){
if (typeof someName == 'number')
... (convert or handle exception, whatever)
return object[name].getText();
}
...
*Note these are just examples and these promises can be handled in a variety of ways in the page object or main tests
The issue comes from attempting to "cycle" through the object. Given that the particular test is attempting to verify, among other things, that all the elements are on the particular web page I am attempting to loop through these objects using the "isPresent()" function. I have made many attempts, and for brevities sake I will not list them here, however they include creating a wrapper promise (using "Q", which I must admit I have no idea how it works) and attempting to run the function in the 'expect' hoping that the jasmine core will wait for all the looping promises resolve and then read the output (it was more of a last ditch effort really).
You should loop like you did before on all of the elements, if you want it in a particular order, create a recursive function that just calls itself with the next element in the JSON.
Now, to handle jasmine specs finishing before and that stuff.
this function needs to be added to protractor's flow control for it to wait to continue, read more about it here. and also, dont use Q in protractor, use protractor's implementation of webdriverJS promises.
Also, consider using isDisplayed instead, assuming you want it to be dispalayed on the page.
So basically, your code skeleton will look like this:
it(.....{
var flow = webdriver.promise.controlFlow();
return webdriver.execute(function () {//your checks on the page here,
//if you need extract to external function as i described in my first paragraph
well i think that should provide you enough info on how to handle waiting for promises in protractor, hope i helped.

How can I attach an event handler to the process's exit in a native Node.js module?

I'm working on implementing correct memory management for a native Node.js module. I've ran into the problem described in this question:
node.js native addon - destructor of wrapped class doesn't run
The suggested solution is to bind the destructors of native objects to process.on('exit'), however the answer does not contain how to do that in a native module.
I've taken a brief look at the libuv docs as well, but they didn't contain anything useful in this regard, either.
NOTE: I'm not particularly interested in getting the process object, but I tried it that way:
auto globalObj = NanGetCurrentContext()->Global();
auto processObj = ::v8::Handle<::v8::Object>::Cast(globalObj->Get(NanNew<String>("process")));
auto processOnFunc = ::v8::Handle<::v8::Function>::Cast(processObj->Get(NanNew<String>("on")));
Handle<Value> processOnExitArgv[2] = { NanNew<String>("exit"), NanNew<FunctionTemplate>(onProcessExit)->GetFunction() };
processOnFunc->Call(processObj, 2, processOnExitArgv);
The problem then is that I get this message when trying to delete my object:
Assertion `persistent().IsNearDeath()' failed.
I also tried to use std::atexit and got the same assertion error.
So far, the best I could do is collecting stray ObjectWrap instances in an std::set and cleaning up the wrapped objects, but because of the above error, I was unable to clean up the wrappers themselves.
So, how can I do this properly?
I was also getting the "Assertion persistent().IsNearDeath()' failed" message.
There is a node::AtExit() function that runs just before Node.js shuts down - the equivalent of process.on('exit').
Pass a callback function to node::AtExit from within your add-on's init function (or where ever is appropriate).
The function is documented here:
https://nodejs.org/api/addons.html#addons_atexit_hooks
For example:
NAN_MODULE_INIT(my_exports)
{
// other exported stuff here
node::AtExit(my_cleanup);
}
NODE_MODULE(my_module, my_exports) //add-on exports
//call C++ dtors:
void my_cleanup()
{
delete my_object_ptr; //call object dtor, or other stuff that needs to be cleaned up here
}

array reference javascript angular

i'm trying to reference one item in an array, and i have no idea why this is not working,
console.log($scope.Times);
console.log($scope.Times[0]);
these two lines of code are EXACTLY after eachother, but the output i get from the console is the following..
Output from the console
any ideas why this is not working? the commands are exactly after each other as I mentioned before and in the same function, the variable is global in my controller.
i can add more code if you think it can help, but i don't really understand how..
some more code:
$scope.Times = [];
$scope.getStatus = function(timer){
$http.post('getStatus.php', {timer : timer})
.success(function(response){
$scope.response = response;
if ($scope.response.Running === "0"){
$scope.model = { ItemNumber : $scope.response.Part };
$scope.loadTiming($scope.response.Part);
console.log($scope.Times);
console.log($scope.Times[0]);
}
});
};
$scope.loadTiming = function(itemNumber) {
$http.post('getPartTimings.php', {itemNumber : itemNumber})
.success(function(response){
$scope.selectedTiming = response;
$scope.Times.splice(0);
var i = 0;
angular.forEach($scope.selectedTiming, function(value) {
if (value !== 0)
$scope.Times.push({
"Process" : $scope.procedures[i],
"Duration" : value*60
});
i++;
});
});
};
<?php
$postData = file_get_contents("php://input");
$request = json_decode($postData);
require "conf/config.php";
mysqli_report(MYSQLI_REPORT_STRICT);
try {
$con=mysqli_connect(DBSERVER,DBUSER,DBPASS,DBNAME);
} catch (Exception $exp) {
echo "<label style='font-weight:bold; color:red'>MySQL Server Connection Failed. </label>";
exit;
}
$query = 'SELECT *,
TIME_TO_SEC(TIMEDIFF(NOW(),Timestamp))
FROM live_Timers
WHERE Timer='.$request->timer;
$result = mysqli_query($con, $query);
$data = mysqli_fetch_assoc($result);
echo JSON_ENCODE($data);
thanks for your help.
OK, so more code does help. It looks like you have asynchronous logic happening here. loadTiming is fired, which does a POST and then a splice on the Times array. One console.log could be firing before this POST and the other after. There's no easy way to tell.
One possible fix would be to only log these once the loadTiming async process runs. Return a promise from the loadTiming function and then in the then callback of the promise, log your array.
$scope.getStatus = function(timer){
$http.post('getStatus.php', {timer : timer})
.success(function(response){
$scope.response = response;
if ($scope.response.Running === "0"){
$scope.model = { ItemNumber : $scope.response.Part };
$scope.loadTiming($scope.response.Part).then(function () {
console.log($scope.Times);
console.log($scope.Times[0]);
});
}
});
};
$scope.loadTiming = function(itemNumber) {
return $http.post('getPartTimings.php', {itemNumber : itemNumber})
.success(function(response){
$scope.selectedTiming = response;
$scope.Times.splice(0);
var i = 0;
angular.forEach($scope.selectedTiming, function(value) {
if (value !== 0)
$scope.Times.push({
"Process" : $scope.procedures[i],
"Duration" : value*60
});
i++;
});
});
};
I think your issue is a $scope reference issue.
I would try this:
$scope.vm = {};
$scope.vm.Times = [];
Adding the "." is Angular best practice when attaching to $scope. This is best described here Understanding Scopes
I have experienced a similar situation a while ago, related with this issue.
Since then, I've encountered related issues a bunch of times (AngularJS, due to its cyclic nature seems prone to produce this behaviour).
In your case, using JSON.stringify($scope.Times) might "fix" this.
Context
Usually this happens in this context:
An async call or a expensive DOM manipulation is made.
You make 2 (or more) calls to console.log in between.
The state of the DOM or object is changed
The output shows inconsistent (and strange) results
How
Take this example:
console.log(someObject);
console.log(someObject.property);
After digging a lot (and talking to Webkit developers) this is what I've found:
The second call to console.log is "resolved" first.
Why?
In your case, this has to do how Console handles objects and "expressions" in a different way:
An "expression" is resolved in the time of call, while with objects, a reference to said object is stored instead
Note that expression is used loosely here. You can observe this behaviour in this fiddle
More in depth analysis
Regarding display discrepancies, the behaviour posted above is not the only gotcha with Console. In fact, it is related in how Console works.
Console is an external tool
First you must realize that Console is an external tool and not part of the ECMAScript spec. Implementations differ between browsers and it shouldn't be used in production. It certainly won't work the same for every user.
Console is a non-standard external tool and is not on a standards track.
Console is dynamic
Console as a very dynamic tool. With console you can make assertions (test), time and profile your code, group log entries, remote connect to your server and debug Server Side Code. You can even change code itself, at runtime. So..
Console is not just a static log displayer... Its dynamic nature is one its most features
Console has a slight delay
Being an external dynamic tool, Console works as a watcher process attached to the javascript engine.
This is useful in debugging and among other things prevents Console to inadvertently block the execution of the script. A simple and crude way of thinking about this is picturing console.log as a kind of non-blocking async call. This means that:
With Console, there's a slight delay between 1)call, 2)processing and 3)output.
However, calling Console is not "instant" per se. In fact, by itself, can delay script execution. If you mix this with complex DOM manipulations and events, it can cause weird behaviours.
I've encountered an issue with Chrome, when using MutationObserver and console.log. This happened because the DOM Painting was delaying the update of the DOM object but the event triggered by that DOM change was fired nevertheless. This meant the event callback was executed and finished before the DOM Object was fully updated, resulting in an invalid reference to the DOM object.
Using console.log in the observer caused a brief delay in the callback execution, that, in most of the times, was enough to let the DOM Object update first. This proves that console.log delays code execution.
But even when an invalid reference error occurred, console.log ALWAYS showed a valid object. Since the object couldn't have been changed by code itself, this proves there is a delay delay between the call of console.log and the processing.
Console log order matches the code path
Console log entries order is unaffected by entries update status. In other words,
The order of the log entries reflect the order in which they are called, not their "freshness"
So, if an object is updated, it does not move to the end of the log. (makes sense to me)
Counterintuitive behaviour
This can lead to a number of possible counterintuitive behaviours because one might expect a console.log to be some kind of snapshot of the object, not a reference to it.
For instance, in your case, the object is changed between the the call to console.log and the end of the script.
At the time of calling, $scope.Times is empty, so $scope.Times[0] is undefined.
However, the $scope.Time object is updated posteriorly.
When the Console report is displayed, it shows an updated version of the object.
Fix
In your case, transforming the object in an "expression" can solve the "issue". For instance, you can use JSON.stringify($scope.Times).
Debate
It is debatable if the way console handles objects is a Bug or a Feature. Some propose that, when called with an object, console.log should clone that object making a kind of snapshot. Some argue that storing a reference to the object is preferable, since you can easily create a snapshot yourself if you wish to do so.

immutable chrome sqlite return objects

I am using a sqlite DB as a storage system for a webapp. I been using the objects that are returned from queries directly in application. For example:
function get_book_by_id(id,successCallback,errorCallback)
{
function _successCallback(transaction, results)
{
if(results.rows.length==0) {successCallback(null);}
else
{
book=results.rows.item(0);
successCallback(book);
}
}
db.transaction(
function (transaction) {
transaction.executeSql("SELECT id,title,content,last_read from books where id=?;",[id], _successCallback, errorCallback);
});
}
This returns me an object with the given id, all columns are provided as properties. Nice. The problem I just figured out is that all the properties of the result set object are immutable. So for example if I want to change the property 'title' it takes no effect, which in my opinion makes no sense. Example:
get_book_by_id(1,handle,error);
function handle(book)
{
//THIS DOESN'T WORK, book.title is still what it was.
book.title=book.title+"more text";
}
I of course can convert all my DB objects into mutable objects, but I rather would not do that.
Is that an expected behavior? Can I request mutable objects?
I am using google chrome 9.0 on Mac OS X.
The WebSQL spec doesn't require for the returned item to be sealed, but it's up to the implementation (the spec does require for the item to be an ordered dictionary with the properties in the same order as the columns in your query).
And no, there is no way to explicitly request a mutable object, so you'll want to do something like the convert_to_mutable() approach suggested by Stan.
BTW, assuming you're using a 3rd party library, it probably has a function for this, for example jQuery.extend() or _.extend().
Building on Stepan's answer, but for people like me that want a quick fix from SO.
You can create another basic object and copy the sqlite row properties onto it.
Something like this:
var immutable_book = results.rows.item(0);
var book = {};
for (var prop in immutable_book) {
if (immutable_book.hasOwnProperty(prop)) {
book[prop] = immutable_book[prop];
}
}
That goes in the _successCallback, and then later you can do this:
book.title=book.title+"more text"; // works now !
I came across this issue in iOS Safari, but in Chrome and Android web-kit browsers I was able to update properties of the returned row object directly.

Categories

Resources