Javascript promise - replace arrow functions - javascript

Since the support for arrow functions in JS is still quite low, I'd like to replace them from the following code snippet:
Promise.all([f1(), f2()])
.then(values => { f3(values); })
.catch(values => { f4(values); });
Any idea how can this be achieved?

Should be straight forward, just type "function" instead
Promise.all([f1(), f2()]).then(function(values) {
f3(values);
}).catch(function(values) {
f4(values);
});

Why are you using function expressions at all in there? Do you want to avoid the return values? If not, just go for
Promise.all([f1(), f2()]).then(f3).catch(f4);

This is a solution I wrote to allow existing promise-based code work on promise-less browsers like IE11. Not perfect, but works well.
CanPromise = !!window.Promise;
PromiseResolve = [];
PromiseReject = [];
if (!CanPromise)
{
window.Promise = function (f)
{
var p = {};
p.resolve = function (result)
{
PromiseResolve.push(result);
}
p.reject = function (result)
{
PromiseReject.push(result);
}
return f(p.resolve, p.reject);
};
}
//...........
PromiseResolve.length = 0;
PromiseReject.length = 0;
F1(args);
F2(args);
var AjaxTimeout = 10000;
var period = 100;
var cnt = 0;
var cntMax = parseInt(AjaxTimeout / period);
var t = setInterval(function ()
{
if (PromiseReject.length > 0)
{
clearInterval(t);
Error(PromiseReject[0]);
}
else if (PromiseResolve.length >= 2)
{
clearInterval(t);
Success(PromiseResolve);
}
else if (cnt >= cntMax)
{
clearInterval(t);
}
cnt++;
}, period);

Related

Pure js code works in Firefox but not Chrome

The code below works fine in Firefox, in Chrome it behaves quite strage. For short loops(below several hundreds) it works, but for large it never ends. Sometimes it can break from that infinite loop and complete.
This could be fixed by replacing "delete _scope.context" with _scope.context=undefined
Can someone elaborate what is going on here?
(function() {
var _module = function() {
const _scope = function() {
var a = 0,
block = 0;
var suspend = function() {
var context = {};
context.a = a;
context.block = block;
context.resume = function() {
_scope.context = context;
return _scope();
}
_scope.context = context;
return context;
}
var awake = function() {
context = _scope.context;
delete _scope.context;
//_scope.context = undefined;
a = context.a;
block = context.block;
}
if (_scope.context !== undefined) {
awake();
}
while (true) {
switch (block) {
case 0:
block = 1;
return suspend();
case 1:
block = 0;
if (a++ > 10000) {
return;
}
continue;
}
}
}
return _scope();
}
var runMod = function() {
var susp = _module();
var nSteps = 0;
while (susp) {
susp = susp.resume();
if (!(++nSteps % 1000)) {
console.log(nSteps, susp);
}
if (nSteps > 100000) {
console.log('aborted')
break;
}
}
console.log('complete', nSteps);
}
runMod();
})()
.as-console-wrapper {
max-height: 100% !important;
}
https://jsfiddle.net/daborkpw/
This is a bug in Chrome, will be fixed in 75
The fix https://chromium-review.googlesource.com/c/v8/v8/+/1617251/6/src/runtime/runtime-object.cc#84

how to execute second method only after first method is executed

I want to print a heading tag only after a paragraph tag is loaded. Below is my Javascript code. See the plunker for more clarification: http://embed.plnkr.co/aheHkSQUBft5A4Z3wkie/preview
function changeText(cont1, cont2, speed){
var Otext = cont1.text();
var Ocontent = Otext.split("");
var i = 0;
function show() {
if (i < Ocontent.length) {
cont2.append(Ocontent[i]);
i = i + 1;
};
};
var Otimer = setInterval(show, speed);
};
$(document).ready(function() {
changeText($("p"), $(".p2"), 30);
clearInterval(Otimer);
});
$(document).ready(function() {
changeText($("h2"), $(".h2"), 30);
clearInterval(Otimer);
});
I would do something like this (please not that ES6 Promises aren't supported by Internet Explorer, but there are shims to use Promises with old browsers too).
You'll have to fill out the parts commented to get it to work though:
var Otimer;
/*#TODO: refactor show() function to use ES6 Promises (eventually with shims) */
function show(Ocontent) {
var i = 0;
if (i < Ocontent.length) {
cont2.append(Ocontent[i]);
i = i + 1;
};
if (Otimer === undefined) {
Otimer = setInterval(show, speed); // Remember to fulfill the promise and remove the interval once it's finished
}
// return the promise
};
function changeText(p1, p2, speed) {
var Otext = p1.text();
var Ocontent = Otext.split("");
return show(Ocontent);
};
$(function () {
changeText($("p"), $(".p2"), 30).then(function() { // We call changeText the second time after the promise return by changeText() is fulfilled and the show() function has finished
Otimer = undefined;
changeText($("h2"), $(".h2"), 30);
});
});
first of all, variable declaring inside of function is scoped variable, which You cannot access from outside of the function.
so the line clearInterval(Otimer); never works.
the code below is fixed code of the scope issue and using callback to implement what you want.
function changeText(cont1, cont2, speed, cb) {
var Otext = cont1.text();
var Ocontent = Otext.split("");
var i = 0;
function show() {
if (i < Ocontent.length) {
cont2.append(Ocontent[i]);
i++;
}else{
clearInterval(Otimer)
if(cb) cb()
}
};
var Otimer = setInterval(show, speed);
};
$(document).ready(function() {
changeText($("p"), $(".p2"), 30, function(){
changeText($("h2"), $(".h2"), 30);
});
});
http://plnkr.co/edit/xowItFUWqI79obi4ZVNV?p=preview

How set a timeout every 50 iterations in an array.map() loop?

Question: How can I make my files.map(...) pause every 50 iterations?
Problem: the gm().size() is a very expensive function. which completely shits the bed after about 300 iterations. I have a theory that this will be remedied if I let the function keep up.
//interaction happens that will traverse a bunch of folder and create an array of files paths
glob(filePath + '/**/*{.png,.jpg,.gif}', function (er, files) {
var chunksize = 50; // sets the iteration size
if (er) return er;
service.stuff[name] = files.map(function (entry, i) {
return {
identity: getIdentity() //returns the identity(size) of images
};
function getIdentity() {
if(i % chunksize == 0) { // if the 50th iteration
(function(chunksize, i){
setTimeout(function () {
var entrySize = gm(entry) //graphics magic will return size of images based on path.
.size(function (err, size) {
return size;
});
}, 2000); //pause for 2 seconds.
}());
} else {
var entrySize = gm(entry)
.size(function (err, size) {
return size;
});
}
return entrySize.data; //returns identity data.
}
});
});
Alternatively, implement your own batch processor. This alternative to map will only process options.batchSize items at a time, then takes an options.timeoutMs break to give the application time to do other things.
function batchMap(array, fn, options, callback) {
var batchSize = options.batchSize || 100,
timeoutMs = options.timeoutMs || 0;
function map(done, todo) {
if(todo.length > 0) {
setTimeout(function() {
var mapped = todo.slice(0, batchSize).map(fn);
map(done.concat(mapped), todo.slice(batchSize));
}, timeoutMs);
} else {
callback(null, done);
}
}
map([], array);
}
You can use async.mapSeries for this. It waits for each iteration to finish before continuing to the next.
npm install async
var async = require("async");
var noFile = 0;
var done = function (err, result) {
console.log(result);
}
var yourLogic = function(file){
}
var processFile = function(file, callback) {
if(noFile > 50) {
setTimeout(function() {
noFile++;
callback(null, yourLogic(file));
}, 1000);
} else {
noFile++;
callback(null, yourLogic(file));
}
}
async.mapSeries(files, processFile, done);
Sorry, I just feel like shamelessly plugging my new library so I will. It goes something like this:
var CL = require('coastline');
CL.run(function* () {
var files = yield glob(filePath + '/**/*{.png,.jpg,.gif}', CL.cb());
var chunksize = 50;
service.stuff[name] = yield CL.map(files, function* (entry, i) {
if (i && i % chunksize == 0) yield CL.sleep(2000);
var entrySize = yield gm(entry).size(CL.cb());
return {
identity: entrySize.data
};
});
});
Edit: checked and it works, except there is no .data in entrySize, just .width and .height?
Edit: removed var i since we can use array index.

Javascript callback managment

I'm having trouble with designing a class which exposes its actions through callbacks. Yes my approach works for me but also seems too complex.
To illustrate the problem I've drawn the following picture. I hope it is useful for you to understand the class/model.
In my approach, I use some arrays holding user defined callback functions.
....
rocket.prototype.on = function(eventName, userFunction) {
this.callbacks[eventName].push(userFunction);
}
rocket.prototype.beforeLunch = function(){
userFunctions = this.callbacks['beforeLunch']
for(var i in userFunctions)
userFunctions[i](); // calling the user function
}
rocket.prototype.lunch = function() {
this.beforeLunch();
...
}
....
var myRocket = new Rocket();
myRocket.on('beforeLunch', function() {
// do some work
console.log('the newspaper guys are taking pictures of the rocket');
});
myRocket.on('beforeLunch', function() {
// do some work
console.log('some engineers are making last checks ');
});
I'm wondering what the most used approach is. I guess I could use promises or other libraries to make this implementation more understandable. In this slide using callbacks is considered evil. http://www.slideshare.net/TrevorBurnham/sane-async-patterns
So, should I use a library such as promise or continue and enhance my approach?
var Rocket = function () {
this.timer = null;
this.velocity = 200;
this.heightMoon = 5000;
this.goingToMoon = true;
this.rocketStatus = {
velocity: null,
height: 0,
status: null
};
this.listener = {
};
}
Rocket.prototype.report = function () {
for (var i in this.rocketStatus) {
console.log(this.rocketStatus[i]);
};
};
Rocket.prototype.on = function (name,cb) {
if (this.listener[name]){
this.listener[name].push(cb);
}else{
this.listener[name] = new Array(cb);
}
};
Rocket.prototype.initListener = function (name) {
if (this.listener[name]) {
for (var i = 0; i < this.listener[name].length; i++) {
this.listener[name][i]();
}
return true;
}else{
return false;
};
}
Rocket.prototype.launch = function () {
this.initListener("beforeLaunch");
this.rocketStatus.status = "Launching";
this.move();
this.initListener("afterLaunch");
}
Rocket.prototype.move = function () {
var that = this;
that.initListener("beforeMove");
if (that.goingToMoon) {
that.rocketStatus.height += that.velocity;
}else{
that.rocketStatus.height -= that.velocity;
};
that.rocketStatus.velocity = that.velocity;
if (that.velocity != 0) {
that.rocketStatus.status = "moving";
}else{
that.rocketStatus.status = "not moving";
};
if (that.velocity >= 600){
that.crash();
return;
}
if (that.rocketStatus.height == 2000 && that.goingToMoon)
that.leaveModules();
if (that.rocketStatus.height == that.heightMoon)
that.landToMoon();
if (that.rocketStatus.height == 0 && !that.goingToMoon){
that.landToEarth();
return;
}
that.report();
that.initListener("afterMove");
that.timer = setTimeout(function () {
that.move();
},1000)
}
Rocket.prototype.stop = function () {
clearTimeout(this.timer);
this.initListener("beforeStop");
this.velocity = 0;
this.rocketStatus.status = "Stopped";
console.log(this.rocketStatus.status)
this.initListener("afterStop");
return true;
}
Rocket.prototype.crash = function () {
this.initListener("beforeCrash");
this.rocketStatus.status = "Crashed!";
this.report();
this.stop();
this.initListener("afterCrash");
}
Rocket.prototype.leaveModules = function () {
this.initListener("beforeModules");
this.rocketStatus.status = "Leaving Modules";
this.initListener("afterModules");
}
Rocket.prototype.landToMoon = function () {
this.initListener("beforeLandToMoon");
this.rocketStatus.status = "Landing to Moon";
this.goingToMoon = false;
this.initListener("afterLandToMoon");
}
Rocket.prototype.landToEarth = function () {
this.initListener("beforeLandToEarth");
this.stop();
this.rocketStatus.status = "Landing to Earth";
this.initListener("afterLandToEarth");
}
Rocket.prototype.relaunch = function () {
this.initListener("beforeRelaunch");
this.timer = null;
this.velocity = 200;
this.heightMoon = 5000;
this.goingToMoon = true;
this.rocketStatus = {
velocity: 200,
height: 0,
status: "relaunch"
};
this.launch();
this.initListener("afterRelaunch");
}
init;
var rocket = new Rocket();
rocket.on("afterLaunch", function () {console.log("launch1")})
rocket.on("afterLandToMoon", function () {console.log("land1")})
rocket.on("beforeLandToEarth", function () {console.log("land2")})
rocket.on("afterMove", function () {console.log("move1")})
rocket.on("beforeLaunch", function () {console.log("launch2")})
rocket.launch();
You can add any function before or after any event.
This is my solution for this kinda problem. I am not using any special methods anything. I was just wonder is there any good practise for this like problems. I dig some promise,deferred but i just can't able to to this. Any ideas ?

how to clear all javascript Timeouts?

i have a loop function that in first 5 seconds it runs social1() and in second 5 seconds it runs social2() then loop ...
i have 2 hover functions too
i need clear all active timeouts because when i hover on images (.social1 & .social2), i can see that multiple timeouts are running
how to fix this?
function social1() {
$('.social1').fadeTo(500, 1);
$('.social2').fadeTo(500, 0.5);
timeout = setTimeout(function() {
social2();
}, 5000);
}
function social2() {
$('.social1').fadeTo(500, 0.5);
$('.social2').fadeTo(500, 1);
timeout = setTimeout(function() {
social1();
}, 5000);
}
$(document).ready(function ()
{
social1();
$('.social1').hover(
function () {
window.clearTimeout(timeout);
social1();
},
function () {
timeout = setTimeout(function() {
social2();
}, 5000);
}
);
$('.social2').hover(
function () {
window.clearTimeout(timeout);
social2();
},
function () {
timeout = setTimeout(function() {
social1();
}, 5000);
}
);
__EDIT__
To manage a collection of timeouts (and intervals), you could use following snippet.
This will allow to clear any timeouts or intervals set anywhere in code, although, you have to set this snippet before setting any timeout or interval. Basically, before processing any javascript code or external script which uses timeout/interval.
JS:
;(function () {
window.timeouts = {},
window.intervals = {},
window.osetTimeout = window.setTimeout,
window.osetInterval = window.setInterval,
window.oclearTimeout = window.clearTimeout,
window.oclearInterval = window.clearInterval,
window.setTimeout = function () {
var args = _parseArgs('timeouts', arguments),
timeout = window.osetTimeout.apply(this, args.args);
window.timeouts[args.ns].push(timeout);
return timeout;
},
window.setInterval = function () {
var args = _parseArgs('intervals', arguments),
interval = window.osetInterval.apply(this, args.args);
window.intervals[args.ns].push(interval);
return interval;
},
window.clearTimeout = function () {
_removeTimer('timeouts', arguments);
},
window.clearInterval = function () {
_removeTimer('intervals', arguments);
},
window.clearAllTimeout = function () {
_clearAllTimer('timeouts', arguments[0]);
},
window.clearAllInterval = function () {
_clearAllTimer('intervals', arguments[0]);
};
function _parseArgs(type, args) {
var ns = typeof args[0] === "function" ? "no_ns" : args[0];
if (ns !== "no_ns")[].splice.call(args, 0, 1);
if (!window[type][ns]) window[type][ns] = [];
return {
ns: ns,
args: args
};
}
function _removeTimer(type, args) {
var fnToCall = type === "timeouts" ? "oclearTimeout" : "oclearInterval",
timerId = args[0];
window[fnToCall].apply(this, args);
for (var k in window[type]) {
for (var i = 0, z = window[type][k].length; i < z; i++) {
if (window[type][k][i] === timerId) {
window[type][k].splice(i, 1);
if (!window[type][k].length) delete window[type][k];
return;
}
}
}
}
function _clearAllTimer(type, ns) {
var timersToClear = ns ? window[type][ns] : (function () {
var timers = [];
for (var k in window[type]) {
timers = timers.concat(window[type][k]);
}
return timers;
}());
for (var i = 0, z = timersToClear.length; i < z; i++) {
_removeTimer(type, [timersToClear[i]]);
}
}
}());
How to use it:
Set timeout(s)/interval(s) as usual:
var test1 = setTimeout(function(){/**/, 1000);
var test2 = setTimeout(function(){/**/, 1000);
Then you could use to clear both:
clearAllTimeout(); // clearAllInterval(); for intervals
This will clear both timeouts (test1 & test2)
You can use some namespaces to clear only specific timers, e.g:
// first (optional) parameter for setTimeout/setInterval is namespace
var test1 = setTimeout('myNamespace', function(){/**/, 1000); // 'myNamespace' is current namespace used for test1 timeout
var test2 = setTimeout(function(){/**/, 1000); // no namespace used for test2 timeout
Again, clearAllTimeout(); will clear both timeouts. To clear only namespaced one, you can use:
clearAllTimeout('myNamespace'); // clearAllInterval('myNamespace'); for namespaced intervals
This will clear only test1 timeout
You could for some reason wish to delete non namespaced timeouts only. You could then use:
clearAllTimeout('no_ns'); // clearAllInterval('no_ns'); for non namespaced intervals only
This will clear only test2 timeout in this example
See jsFiddle DEMO
__END of EDIT__
Old post specific to opening question here:
You could try that:
var timeouts = [];
timeouts.push(setTimeout(function() {
social2();
}, 5000));
timeouts.push(setTimeout(function() {
social1();
}, 5000));
//etc...
function clearAllTimeouts(){
for(var i = 0, z = timeouts.length; i < z; i++)
clearTimeout(timeouts[i]);
timeouts = [];
}
UPDATED following David Thomas comment
var timeouts = {'social' : [], 'antisocial' : []};
//a social timeout
timeouts.social.push(setTimeout(function() {
social1();
}, 5000));
//an anti-social timeout
timeouts.antisocial.push(setTimeout(function() {
antisocial1();
}, 5000));
function clearTimeouts(namespace){
for(var i = 0, z = timeouts[namespace].length; i < z; i++)
clearTimeout(timeouts[namespace][i]);
timeouts[namespace] = [];
}
//usage e.g
clearTimeouts("social");
//Incase if you are looking for full fledged code
var dict = {};
function checkForIntervals(id){
var index = index;
var result = findOrAddProperty(id);
if(result.length != 0){
clearTimeoutsFor(id);
}
dict[id].push(setTimeout(function(){alertFunc(id,index);}, 60000));
};
// to clear specific area timeout
function clearTimeoutsFor(namespace){
for(var i = 0, z = dict[namespace].length; i < z; i++)
clearTimeout(dict[namespace][i]);
dict[namespace] = [];
}
to clear all timeouts
function clearAllTimeOuts(){
for (key in dict) {
for(var i = 0, z = dict[key].length; i < z; i++)
clearTimeout(dict[key][i]);
dict[key] =[];
}
};
function findOrAddProperty(str){
var temp = [];
for (key in dict) {
if(key == str){
if (dict.hasOwnProperty(key)) {
temp = dict[key];
break;
}
}
}
if(temp.length == 0){
dict[str] = [];
}
return temp;
};
function alertFunc(id,index) {
jQuery(document).ready(function($) {
do the ajax call here after 1 min
});
};

Categories

Resources