Simpleish react question that is evading me for a second:
readData: function(){
var readFromCpDev1 = firebase.database().ref('environments/' + 'cp-dev1');
var envUsersArray = [];
readFromCpDev1.on('value', function(snapshot) {
envUsersArray.push(snapshot.val())
return envUsersArray;
});
console.log(envUsersArray, 'hey');
},
anotherfunc: function(){
}
I have this function and I want to return envUsersArray and use it wherever. Obviously at the moment it is returning a blank array as the readData function is not in the scope of the snapshot function.
How can I pass it down to the readData function and then use it inside another function such as anotherfunc
I know I probably need to call this. somewhere but the logic isn't quite coming to me at the mo
I'd suggest using Promises.
readData: function(){
return new Promise(function(resolve) {
var readFromCpDev1 = firebase.database().ref('environments/' + 'cp-dev1');
var envUsersArray = [];
readFromCpDev1.on('value', function(snapshot) {
envUsersArray.push(snapshot.val())
resolve(envUsersArray);
});
});
},
anotherfunc: function(){
this.readData().then(function(arr) {
//do stuff here
});
}
You may return a promise that will resolve with value that is retrieved asynchronously:
readData: function() {
var readFromCpDev1 = firebase.database().ref('environments/' + 'cp-dev1');
var envUsersArray = [];
return new Promise(function(success) {
readFromCpDev1.on('value', function(snapshot) {
envUsersArray.push(snapshot.val())
success(envUsersArray);
}
});
},
anotherfunc: function(){
this.readData().then(function(result) {
console.log(result);
});
}
Related
Is it possible to get sinon to resolve an argument, when the argument is a defered object?
Consider this:
function needToTest() {
var isInitialized = q.defer();
var importantResult;
var publicStuff;
publicStuff.isInitialized = isInitialized.promise.then(function(res) {
importantResult = res;
});
var someClass = new SomeClass(isInitialized);
publicStuff.getResult = function() {
return importantResult;
};
return publicStuff;
}
I use q as promise library, but it's not important.
SomeClass looks something like this:
function SomeClass(promise) {
this.foo = function() {
//
};
//after some initializing:
var result = true; //or false
promise.resolve(result);
}
It might be that this mock should have some sort of function to resolve a promise, but this is what I have so far:
var someClassMock = sinon.stub().withArgs(q.defer());
someClass.prototype.foo = sinon.stub().returns('foo');
return someClassMock;
and ultimately I try to create a testcase using sinon and Squire like this:
describe('test', function() {
var needToTestInstance;
beforeEach(function(done) {
new Squire()
.mock('someClassMock', someClassMock)
.require(['needToTest'], function(module) {
needToTest = module;
//Need to get the needToTest().isInitialized to resolve with a value!
done();
});
});
describe('importantResult', function() {
expect(needToTestInstance.getResult()).to.be(true);
});
});
Is it possible to get isInitialized to resolve at any point in the test?
I need run several function parallel inside promise.then()
I tried to use code like bellow, but it work not correct:
function fadeElement(selector){
return function () {
return $(selector).fadeOut(400).promise();
}
}
function runParallel(owner, promises) {
return function () {
var differed = new $.Deferred();
var resolveDiffered = function () { differed.resolve(); };
$.when.apply(owner, promises).
then(resolveDiffered);
return differed.promise();
}
}
FormInput.prototype.ReloadPage = function(){
var firstOne = fadeElement('#element_Id_1');
var firstTwo = fadeElement('#element_Id_2');
var firstThree = fadeElement('#element_Id_3');
var secondOne = fadeElement('#element_Id_4');
var thirdOne = fadeElement('#element_Id_5');
var thirdTwo = fadeElement('#element_Id_6');
$.when(firstOne(), firstTwo(), firstThree())
.then(secondOne)
.then(
runParallel(this, [thirdOne(), thirdTwo()])
);
}
firstOne, firstTwo, firstThree, secondOne are runs without 400ms duration.
thirdOne, thirdTwo - not run at all.
I think I have a mistake in runParallel, but I havn't enough knowledge to understend where. I think so, becouse this code will work:
$.when(firstOne(), firstTwo(), firstThree())
.then(secondOne)
.then(thirdOne)
.then(thirdTwo);
The problem is that you were calling thirdOne and thirdTwo (and thus starting the fading process) when you passed those functions to runParallel:
.then(
runParallel(this, [thirdOne(), thirdTwo()])
);
Instead, you should remove the final () and pass functions to runParallel, which should map each method to the result of calling it. Changing the placement of when each promise-generating function is called will allow the fading process to be delayed until be after the other promises have completed:
function fadeElement(selector) {
return function() {
return $(selector).fadeOut(400).promise();
}
}
function runParallel(owner, promises) {
return function() {
return $.when.apply(owner, promises.map($.call, $.call))
}
}
FormInput.prototype.ReloadPage = function() {
var firstOne = fadeElement('#element_Id_1');
var firstTwo = fadeElement('#element_Id_2');
var firstThree = fadeElement('#element_Id_3');
var secondOne = fadeElement('#element_Id_4');
var thirdOne = fadeElement('#element_Id_5');
var thirdTwo = fadeElement('#element_Id_6');
$.when(firstOne(), firstTwo(), firstThree())
.then(secondOne)
.then(
runParallel(this, [thirdOne, thirdTwo])
);
}
function FormInput () {
}
new FormInput().ReloadPage()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="element_Id_1">1</div>
<div id="element_Id_2">2</div>
<div id="element_Id_3">3</div>
<div id="element_Id_4">4</div>
<div id="element_Id_5">5</div>
<div id="element_Id_6">6</div>
The code looks like this
function Scripts() {this.FindById = function (id) {
this.FindById.constructor.prototype.value = function () {
return document.getElementById(id).value;
}}}
var Control = new Scripts();
Now when i say Control.FindById("T1").value(). I am not able to get the textInput("T1")'s value.
It seems that your code is a bit more complicated then it should be ;-)
Personally I would write it this way (not tested):
function Scripts() {
this.findById = function(id) {
var el = document.getElementById(id);
return {
value: function() {
return el.value;
}
}
}
}
The findById() now closes over a node and returns an interface that can return its value.
Also, your idea sounds a lot like Singleton, so you wouldn't even need the extra Scripts constructor:
var Control = {
findById: function(id) {
var el = document.getElementById(id);
return {
value: function() {
return el.value;
}
}
}
}
Working example: http://jsfiddle.net/YYkD7/
Try this:
function Scripts() {this.FindById = function (id) {
this.FindById.constructor.prototype.value = function () {
return document.getElementById(id).value
}}}
You didn't close the last "}" :-)
In the following code, I want to be able to call bindClickEvents() like so:
App.Utils.Modal.bindClickEvents();
However, I don't understand the syntax necessary to do this.
Current code:
var App = new Object;
App.Modal = {
bindClickEvents: function() {
return $('a.alert-modal').click(function(e) {
return console.log('Alert Callback');
});
}
};
$(document).ready(function() {
return App.Modal.bindClickEvents();
});
You can do it in one go:
var App = {
Modal : {
bindClickEvents : function () {/* ... */}
}
}
or if you want to break that up to separate steps:
var App = {};
App.Modal = {};
Modal.bindClickEvents = function () {/* ... */};
BTW, in reference to your original question title, this is not object chaining. This is object composition. Object chaining is being able to call methods in an object multiple times in a single statement.
Is this what you're trying to do?
var App = {};
App.Utils = {};
App.Utils.Modal = {
bindClickEvents: function() {
return $('a.alert-modal').click(function(e) {
return console.log('Alert Callback');
});
}
};
$(document).ready(function() {
return App.Utils.Modal.bindClickEvents();
});
Prefer the object literal syntax to the Object constructor; some authors go so far as to call the latter an anti-pattern
Here's the simplest way to set up App.Utils.Modal.bindClickEvents();
var App = {
Utils: {
Modal: {
bindClickEvents: function() {
return $('a.alert-modal').click(function(e) {
return console.log('Alert Callback');
});
}
}
}
};
Or you can piece it together one step at a time:
var App = {};
App.Utils = {};
App.Utils.Modal = {};
App.Utils.Modal.bindClickEvents = function() {
return $('a.alert-modal').click(function(e) {
return console.log('Alert Callback');
});
};
I have a json object retrieved from server in my $(document).ready(...); that has an string that I would like to resolve to a function also defined within $(document).ready(...); so, for example:
$(document).ready(function{
$.getJSON(/*blah*/,function(data){/*more blah*/});
function doAdd(left,right) {
return left+right;
}
function doSub(left,right) {
return left-right;
}
});
with json string:
{"doAdd":{"left":10,"right":20}}
One way I thought about was creating an associative array of the function before loading the json:
var assocArray=...;
assocArray['doAdd'] = doAdd;
assocArray['doSub'] = doSub;
Using eval or window[](); are no good as the function may not be called for some time, basically I want to link/resolve but not execute yet.
Change your JSON to
{method: "doAdd", parameters : {"left":10,"right":20}}
Then do
var method = eval(json.method);
// This doesn't call it. Just gets the pointer
Or (haven't tried this)
var method = this[json.method]
How about something like this?
$(function(){
// Function to be called at later date
var ressolvedFunc = null;
// Ajax call
$.getJSON(/*blah*/,function(data){
// Generate one function from another
ressolvedFunc = (function(data) {
var innerFunc;
var left = data.left;
var right = data.right;
// Detect action
for (action in data) {
if (action == "doAdd")
innerFunc = function() {
return left + right;
};
else
innerFunc = function() {
return left - right;
};
}
return innerFunc;
})(data);
});
});
The anonymous function returns fresh function, with the new values stored within the enclosure. This should allow you to call the function at later date with the data previously retrieved from the GET request.
Rich
try this:
var doX = (function() {
var
data = [],
getDo = function(action) {
for(var d in data) {
if (data[d][action]) {
return data[d];
}
}
return null;
};
return {
set: function(sdata) {
data.push(sdata);
},
doAdd: function() {
var add = getDo("doAdd");
if (!add)
return 0;
return add.doAdd.left + add.doAdd.right;
},
doSub: function() {
var sub = getDo("doSub");
if (!sub)
return 0;
return sub.doAdd.left + sub.doAdd.right;
}
};
})();
$(document).ready(function{
$.getJSON(/*blah*/,function(data){ doX.set(data); });
});