How to call global function from promise function? - javascript

When performing the below function:
try {
Auction.deployed().then(function(contractInstance) {
contractInstance.startAuction(auctionname, duration, { from: buyerAddress }).then(function(result) {
console.log("AUCTION HAS STARTED!!");
console.log(result);
updateAuction(result.receipt);
});
});
} catch (err) {}
}
};
updateAuction = function(data) {
console.log("UPDATE AUCTIONS!");
....
The updateAuction function is not called (even though the console.log functions are working correctly and displaying a message). How can I call the updateAuction function?

This is because of the order in which you're defining the promise and the function.
When you use the syntax updateAuction = function () {}, whether or not you use a var, you must define it above the promise code, otherwise it won't be available. This is in the same way that if you were to write the following, it wouldn't work:
var b = a;
var a = 'Hello!';
This seems quite obvious that a won't be available before it's defined. The same thing applies to functions:
var b = function () {
a();
}
var a = function () {
console.log('Hello');
}
The b function won't have access to a, because it's not yet defined.
If, however, you use the definition of function updateAuction() {}, it will be hoisted, meaning it is defined before anything else.
There are many articles regarding how hoisting works, for example this one from scotch.io and this from Mozilla

var updateAuction = function(data) {
console.log("UPDATE AUCTIONS!");
...
}
try {
Auction.deployed().then(function(contractInstance) {
contractInstance.startAuction(auctionname, duration, { from: buyerAddress }).then(function(result) {
console.log("AUCTION HAS STARTED!!");
console.log(result);
updateAuction(result.receipt);
});
});
} catch (err) {}

You must define your function befor try. correct it like this
var updateAuction = function(data) {
console.log("UPDATE AUCTIONS!");
...
}
try {
Auction.deployed().then(function(contractInstance) {
contractInstance.startAuction(auctionname, duration, { from: buyerAddress }).then(function(result) {
console.log("AUCTION HAS STARTED!!");
console.log(result);
updateAuction(result.receipt);
});
});
} catch (err) {}
;

Related

self-executing anonymous functions and call it again

I want to do something like this:
var build= (function(){
//my function body
})();
function test(){
//somthing then call build
build() //i want to call build function again in my code
}
How can I do this?
I tried this in angular:
var buildRoot = (() => {
$SubNode.get({
TypeID: vendorAdminService.NodeType.Category
}, function(data: vendorAdminService.IGetNodeParameters) {
$scope.ProductTree = data.TreeNodeModelItem;
$scope.AjaxLoading = false;
}, function(err) {
// alert(err)
})
})();
$mdDialog.show(confirm).then(function() {
$Category.Remove(node.ID)
buildRoot
}, function() {
});
but it does not work.
Anybody can guide me??
You need to return a function in your IIFE.
If you IIF is not trivial and has many functionalities you could also consider using Reveal Module Pattern.
var build = (function() {
var f = function() {
console.log('hello');
};
f();
return f;
})();
function test() {
build();
}
test();
Just use a named function.
Your IIFE needs to return a function, for later calling. But then is no need for an anonymous function.
function build() {
//my function body
}
or
var build = function () {
//my function body
};
var build = (function() {
var init = function() {
// magic code
};
return {
init: init
}
}());
function test() {
build.init()
}
test();
You include all your functionalities inside your build object, and you'll be able to call them as soon as you return them from inside that object. This effectively is called the revealing module pattern
For more information, read this
I see that there are missing semi-colons ";"
$mdDialog.show(confirm).then(function() {
$Category.Remove(node.ID);
buildRoot();
}, function() {
});

javascript recursive class: undefined method

I have a JavaScript class that is meant to help deal with promises. First you add functions to an array, then it executes them pops them and calls itself to do the next one. At the end of the array it resolves that promise. My hope was to then propagate the resolution all the way up the stack of recursive calls. This will allow you to force multiple asynchronous functions to run sequentially using a simple set of commands. furthermore employ logic to modify the flow of the ansync functions.
function Sequencer() {
this.functionSequence = [];
this.addFunction = function (func) {
this.functionSequence.push(func);
}
this.getFunctionSequence = function () {
return functionSequence;
}
this.executeAll = function () {
var functionList = this.functionSequence;
var deferred = $q.defer();
if (functionList.length > 0) {
functionList[0]().then(function (result) {
if (result) {
functionList.splice(0, 1);
executeAll().then(function (resultInner) {
if (resultInner == true) {
deferred.resolve(true);
} else {
deferred.resolve(false);
}
});
} else {
functionList = [];
deferred.resolve(false);
}
});
} else {
deferred.resolve(true);
}
return deferred.promise;
}
}
I am getting ReferenceError: 'executeAll' is undefined
in this script, on the recursive call line "executeAll' just after the splice
the first function in the array is being executed(I was testing it with a modal pop up) and when it resolves it hits the splice, then it throws the error right on the executeAll line. Am I defining the function incorrectly? Am I calling it correctly as a recursive function?
use this.executeAll - assuming this will be correct, which it wont, so you'll need to account for that as well ... something like var self = this at the top of executeAll, then call self.executeAll
this.executeAll = function() {
var functionList = this.functionSequence;
var deferred = $q.defer();
var self = this; // save reference to this
if (functionList.length > 0) {
functionList[0]().then(function(result) {
if (result) {
functionList.splice(0, 1);
// need to use self here because "this" is not the "this" we want
self.executeAll().then(function(resultInner) {
if (resultInner == true) {
deferred.resolve(true);
} else {
deferred.resolve(false);
}
});
} else {
functionList = [];
deferred.resolve(false);
}
});
} else {
deferred.resolve(true);
}
return deferred.promise;
};
The reason this is not the this you "want" is due to how this works in javascript - there is plenty on info on stack exchange about using this - I'll find and link a good answer shortly
I offer this alternative code
this.executeAll = function() {
return this.functionSequence.reduce(function(promise, item) {
return promise.then(function(result) {
if (result) {
return item();
}
else {
throw "Fail"; // throw so we stop the chain
}
});
}, Promise.resolve(true))
.then(function(result) {
this.functionSequence = []; // clear out the added functions
return true; // fulfilled value is true as per original code
}.bind(this), function(err) {
this.functionSequence = []; // clear out the added functions
if (err == "Fail") {
return false; // convert the "Fail" to a fullfilled value of false as per original code
}
else {
throw err; // any other error - re-throw the error
}
}.bind(this))
};

Mongoose passing class functions

When I pass functions to mongoose, it seems it no longer has a reference to this. Is there a better way to go about this? All functions are simplified for length reasons. I cannot edit the function getUsernameForId to take additional parameters.
I have class:
var class = new function() {
this.func1 = function(data) {
return data + "test";
}
this.func2 = function(data) {
var next = function(username) {
return this.func1(username); // THIS THROWS undefined is not a function
}
mongoose.getUsernameForId(1, func3);
}
}
mongoose is another class like this:
var getUsernameForId = function(id, callback) {
user_model.findOne({"id": id}, function(err, user) {
if(err) {
throw err;
}
callback(user.username);
});
}
How do I resolve the undefined is not a function error. I do not want to duplicate code because func1 is pretty long in reality.
It's not clear from your code how next is used, but if you need it to be invoked with correct this you can try to use Function.prototype.bind method:
this.func2 = function(data) {
var next = function(username) {
return this.func1(username);
}.bind(this);
mongoose.getUsernameForId(1, func3);
}
I assume that you simplified code for the post and next does more things in reality. But if it indeed just returns result of this.func1 then you could shorten it:
var next = this.func1.bind(this);

Java script modify function at run time

enter code hereI have the following code
function a(){alert("a");}
I want to create a function b as
function b(){alert("a"); alert("b");}
My approach is something like
var b = a + alert("b");
This is of course not working. But I am wondering if there is some kind of library supporting this.
Edit: Maybe I need to describe my scenario so that its more clear what I want to achieve.
I am using async.js library to handler multiple async calls. My code looks like
var values = {};
...
function all() {
var allDfd = $.Deferred();
async.parallel(
[function (callback) {
remoteCall(function (result) {
values.v1 = result;
callback(null, 'one');
});
},
function (callback) {
remoteCall(function (result) {
values.v2 = result;
callback(null, "two");
});
},
function (callback) {
remoteCall(function (result) {
values.v3 = result;
callback(null, "three");
});
}], function (err, results) {
allDfd.resolve();
});
return allDfd.promise();
}
Clearly there are a lot of repetitive code that bothers me. So my idea is to create a function asyncCall to perform the boilerplate tasks. The idea is
var values = {};
...
function all() {
var allDfd = $.Deferred();
function getAsyncCall (func, innerCallback, callback) {
return function asyncCall(func, innnerCallback, callback){
func(innerCallback + callback(null)); // combine innerCallBack and callback code
}
}
async.parallel(
[getAsyncCall(remoteCall, function(result){values.v1=result;},callback),
getAsyncCall(remoteCall, function(result){values.v2=result;},callback),
getAsyncCall(remoteCall, function(result){values.v3=result;},callback),
], function (err, results) {
allDfd.resolve();
});
return allDfd.promise();
}
The line with the comment is what I am pondering. I am trying to create a new function that combines inner and outer callbacks.
You can do
var b = function() { a(); alert('b'); }
You could write:
var a=function(){alert("a");}
var b=function(){a(); alert("b");}
And to go a little further, you can even write a whole function composition function:
function compose( functions ) {
return function(){
for(var i=0; i!=functions.length; ++i) {
functions[i]();
}
};
}
var c=compose( [a, function(){ alert("b"); }] );
(See it at work at http://jsfiddle.net/xtofl/Pdrge/)

Chaining ajax requests with jQuery's deferred

I have a web app which must call the server multiple times. So far, I had a long nested callback chain; but I would like to use jQuery's when,then etc. functionality. However, I can't seem to get stuff running again after using a then.
$
.when ($.get('pages/run-tool.html'))
.then (function (args)
{
// This works fine
alert(args);
$('#content').replaceWith (args);
$('#progress-bar').progressbar ({value: 0});
})
.then ($.get('pages/test.html'))
.done (function(args)
{
// This prints the same as the last call
alert (args);
});
What am I doing wrong? I guess its some scoping issue, as I can see the second get call being executed. Using two different args variables does not help as the argument passed to the done function is still the first get request.
As an update:
With modern jquery (1.8+) you don't need the preliminary when because get returns a Deferred Promise.
Also, pipe is deprecated. Use then instead. Just be sure to return the result of the new get which becomes the Promise attached to by subsequent then/*done*/fail calls.
So:
$.get('pages/run-tool.html')
.then (function (args) { // this will run if the above .get succeeds
// This works fine
alert(args);
$('#content').replaceWith (args);
$('#progress-bar').progressbar ({value: 0});
})
.then (function() { // this will run after the above then-handler (assuming it ran)
return $.get('pages/test.html'); // the return value creates a new Deferred object
})
.done (function(args) { // this will run after the second .get succeeds (assuming it ran)
alert (args);
});
All three callbacks (the two with then and the one with done) are applied to the same request – the original when call. This is because then returns the same Deferred object, rather than a new one, so that you can add multiple event handlers.
You need to use pipe instead.
$
.when ($.get('pages/run-tool.html'))
.then (function (args)
{
// This works fine
alert(args);
$('#content').replaceWith (args);
$('#progress-bar').progressbar ({value: 0});
})
.pipe (function() {
return $.get('pages/test.html'); // the return value creates a new Deferred object
})
.done (function(args)
{
alert (args);
});
Here is an wonderfully simple and highly effective AJAX chaining / queue plugin. It will execute you ajax methods in sequence one after each other.
It works by accepting an array of methods and then executing them in sequence. It wont execute the next method whilst waiting for a response.
//--- THIS PART IS YOUR CODE -----------------------
$(document).ready(function () {
var AjaxQ = [];
AjaxQ[0] = function () { AjaxMethod1(); }
AjaxQ[1] = function () { AjaxMethod2(); }
AjaxQ[3] = function () { AjaxMethod3(); }
//Execute methods in sequence
$(document).sc_ExecuteAjaxQ({ fx: AjaxQ });
});
//--- THIS PART IS THE AJAX PLUGIN -------------------
$.fn.sc_ExecuteAjaxQ = function (options) {
//? Executes a series of AJAX methods in dequence
var options = $.extend({
fx: [] //function1 () { }, function2 () { }, function3 () { }
}, options);
if (options.fx.length > 0) {
var i = 0;
$(this).unbind('ajaxComplete');
$(this).ajaxComplete(function () {
i++;
if (i < options.fx.length && (typeof options.fx[i] == "function")) { options.fx[i](); }
else { $(this).unbind('ajaxComplete'); }
});
//Execute first item in queue
if (typeof options.fx[i] == "function") { options.fx[i](); }
else { $(this).unbind('ajaxComplete'); }
}
}
The answer cdr gave, which has the highest vote at the moment, is not right.
When you have functions a, b, c each returns a $.Deferred() object, and chains the functions like the following:
a().then(b).then(c)
Both b and c will run once the promise returned from a is resolved. Since both then() functions are tied to the promise of a, this works similiar to other Jquery chaining such as:
$('#id').html("<div>hello</div>").css({display:"block"})
where both html() and css() function are called on the object returned from $('#id');
So to make a, b, c run after the promise returned from the previous function is resolved, you need to do this:
a().then(function(){
b().then(c)
});
Here the call of function c is tied to the promise returned from function b.
You can test this using the following code:
function a() {
var promise = $.Deferred();
setTimeout(function() {
promise.resolve();
console.log("a");
}, 1000);
return promise;
}
function b() {
console.log("running b");
var promise = $.Deferred();
setTimeout(function () {
promise.resolve();
console.log("b");
}, 500);
return promise;
}
function c() {
console.log("running c");
var promise = $.Deferred();
setTimeout(function () {
promise.resolve();
console.log("c");
}, 1500);
return promise;
}
a().then(b).then(c);
a().then(function(){
b().then(c)
});
Change the promise in function b() from resolve() to reject() and you will see the difference.
<script type="text/javascript">
var promise1 = function () {
return new
$.Deferred(function (def) {
setTimeout(function () {
console.log("1");
def.resolve();
}, 3000);
}).promise();
};
var promise2 = function () {
return new
$.Deferred(function (def) {
setTimeout(function () {
console.log("2");
def.resolve();
}, 2000);
}).promise();
};
var promise3 = function () {
return new
$.Deferred(function (def) {
setTimeout(function () {
console.log("3");
def.resolve();
}, 1000);
}).promise();
};
var firstCall = function () {
console.log("firstCall");
$.when(promise1())
.then(function () { secondCall(); });
};
var secondCall = function () {
console.log("secondCall")
$.when(promise2()).then(function () { thirdCall(); });
};
var thirdCall = function () {
console.log("thirdCall")
$.when(promise3()).then(function () { console.log("done"); });
};
$(document).ready(function () {
firstCall();
});
</script>
I thought I would leave this little exercise here for anyone who may find it useful, we build an array of requests and when they are completed, we can fire a callback function:
var urls = [{
url: 'url1',
data: 'foo'
}, {
url: 'url2',
data: 'foo'
}, {
url: 'url3',
data: 'foo'
}, {
url: 'url4',
data: 'foo'
}];
var requests = [];
var callback = function (result) {
console.log('done!');
};
var ajaxFunction = function () {
for (var request, i = -1; request = urls[++i];) {
requests.push($.ajax({
url: request.url,
success: function (response) {
console.log('success', response);
}
}));
}
};
// using $.when.apply() we can execute a function when all the requests
// in the array have completed
$.when.apply(new ajaxFunction(), requests).done(function (result) {
callback(result)
});
My way is to apply callback function:
A(function(){
B(function(){
C()})});
where A, B can be written as
function A(callback)
$.ajax{
...
success: function(result){
...
if (callback) callback();
}
}

Categories