I have been trying to understand the architecture behind a promise call in javscript and here is something that i assumed is happening behind the scene
function Promise() {
this.stack = [];
this.then = function(fn) {
this.stack.push(fn);
return this;
}
this.resolve = function(data) {
if (this.stack.length) {
var cb = this.stack[0];
this.stack.shift();
cb.call(null, {
resolve: this.resolve.bind(this)
}, data);
}
}
}
// --- below is a working implementation --- //
var bar = function() {
var promise = new Promise();
setTimeout(function() {
console.log("1");
promise.resolve();
}, 2000);
return promise;
}
bar().then(function(p) {
setTimeout(function() {
console.log("2");
p.resolve();
}, 1000);
}).then(function(p) {
setTimeout(function() {
console.log("3");
p.resolve();
}, 500);
}).then(function(p) {
setTimeout(function() {
console.log("4");
p.resolve();
}, 300);
});
in my library, after every resolve call, i am calling the next callback in the stack and shifting the array by one
however in other libraries that i have linked, every-time the first promise is resolved a loop is being run through out the entire array while it keeps calling the callback stacks.
D.js
function execCallbacks() {
/*jshint bitwise:false*/
if (status === 0) {
return;
}
var cbs = pendings,
i = 0,
l = cbs.length,
cbIndex = ~status ? 0 : 1,
cb;
pendings = [];
for (; i < l; i++) {
(cb = cbs[i][cbIndex]) && cb(value);
}
}
tiny Promise.js
_complete: function(which, arg) {
// switch over to sync then()
this.then = which === 'resolve' ?
function(resolve, reject) {
resolve && resolve(arg);
} :
function(resolve, reject) {
reject && reject(arg);
};
// disallow multiple calls to resolve or reject
this.resolve = this.reject =
function() {
throw new Error('Promise already completed.');
};
// complete all waiting (async) then()s
var aThen, i = 0;
while (aThen = this._thens[i++]) {
aThen[which] && aThen[which](arg);
}
delete this._thens;
}
tiny closure Promise.js
function complete(type, result) {
promise.then = type === 'reject' ?
function(resolve, reject) {
reject(result);
} :
function(resolve) {
resolve(result);
};
promise.resolve = promise.reject = function() {
throw new Error("Promise already completed");
};
var i = 0,
cb;
while (cb = callbacks[i++]) {
cb[type] && cb[type](result);
}
callbacks = null;
}
I want to understand, why is there a loop being run through the array to handle the next function chained to the resolve !
what am i missing in my architecture?
in my library, after every resolve call, i am calling the next callback in the stack and shifting the array by one
That's a callback queue, not a promise. A promise can be resolved only once. When making a .then() chain of promises, it simply creates multiple promise objects, each one representing the asynchronous result after a step.
You might want to have a look at the core features of promises.
Related
// read data with progress
function nprogressWrapPromise(fn, hide = false) {
if(hide) {
// no progress
return fn()
}
// have progress
const done = nprogressStartLoad();
return fn().then(() => {
done();
});
}
function print(message) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
console.log(message);
resolve();
}, 1000);
});
}
call nprogressWrapPromise multiple times in different places
nprogressWrapPromise(async () => {
return await print("one")
})
nprogressWrapPromise(async () => {
return await print("two")
})
nprogressWrapPromise(async () => {
return await print("three")
})
I use the NProgress to when I ask the promise ,the page is display the propress
let started = 0;
function nprogressStartLoad() {
if (started == 0) {
window.NProgress.start()
}
started++;
return () => {
started--;
if (started <= 0) {
started = 0;
window.NProgress.done();
}
}
}
I want to add the time, in the five seconds, only the first promise have process, the others promise dont have process.
You can do it like this:
let promise = undefined;
function print(message) {
if (promise) return promise;
return promise = new Promise(function (resolve, reject) {
setTimeout(function () {
console.log(message);
resolve();
promise = undefined;
}, 1000);
});
}
So, we use promise as a semaphor. Whenever a new promise is created, we simply store it into the variable called promise and we will proceed reusing this variable instead of creating a promise for references even while the promise is not resolved yet. Once the promise is resolved, we set promise to undefined, so at the next call of print we will have a new Promise.
EDIT
Similarly to the semaphore above, you can use another semaphore for your other function:
let npprogressWrapPromiseDone = undefined;
// read data with progress
function nprogressWrapPromise(fn, hide = false) {
if(hide) {
// no progress
return fn()
}
if (npprogressWrapPromiseDone) return npprogressWrapPromiseDone;
// have progress
const done = nprogressStartLoad();
return npprogressWrapPromiseDone = fn().then(() => {
done();
});
}
I'm using jasmine-node 1.14.5, which underneath uses jasmine 1.3, and I'm having issues getting runs/waitFor to work properly with Promises.
In certain tests, I'd like to runs/waitFor to wait for a particular condition to happen, and when it occurs, fulfil a Promise that I return back. However, the moment I attempt to construct a Promise passing in the function(success, fail) parameter, none of the code inside the runs/waitFor gets called. However, if the Promise is resolved directly, it works. Any idea the former option does not work?
To give some examples, the following works fine:
it("should support async execution of test preparation and expectations", function(done) {
var p = Promise.resolve("boo")
.then(function() {
var p2 = Promise.resolve("whatever");
runs(function() {
flag = false;
value = 0;
intId = setInterval(function() {
console.log(value);
if (++value == 3) { clearInterval(intId); flag = true; }
}, 500);
});
waitsFor(function() {
return flag;
}, "The Value should be incremented", 5000);
runs(function() {
expect(value).toEqual(3);
});
return p2;
});
p.then(function() {
done();
}).catch(function(err) {
done(err);
});
});
But on the other hand, this does not work because although runs/waitsFor are called without problems, the callbacks inside do not:
it("should support async execution of test preparation and expectations", function(done) {
var p = Promise.resolve("boo")
.then(function() {
return new Promise(function (fulfil, reject) {
runs(function () {
flag = false;
value = 0;
intId = setInterval(function () {
console.log(value);
if (++value == 3) {
clearInterval(intId);
flag = true;
}
}, 500);
});
waitsFor(function () {
return flag;
}, "The Value should be incremented", 5000);
runs(function () {
expect(value).toEqual(3);
fulfil();
});
});
});
p.then(function() {
done();
}).catch(function(err) {
done(err);
});
});
I've also tried the following in the off chance but does not work either, it behaves the same way as the previous example:
it("should support async execution of test preparation and expectations", function(done) {
var p = Promise.resolve("boo")
.then(function() {
var outerFulfil;
var outerReject;
var p2 = new Promise(function(fulfil, reject) {
outerFulfil = fulfil;
outerReject = reject;
});
runs(function() {
flag = false;
value = 0;
intId = setInterval(function() {
console.log(value);
if (++value == 3) { clearInterval(intId); flag = true; }
}, 500);
});
waitsFor(function() {
return flag;
}, "The Value should be incremented", 5000);
runs(function() {
expect(value).toEqual(3);
outerFulfil();
});
return p2;
});
p.then(function() {
done();
}).catch(function(err) {
done(err);
});
});
Any idea how to solve it? Although the first example works, it does not behave the way I want because I only want the promise to be fulfilled once the assertions after the waitsFor have been carried out.
Cheers,
Galder
I ended up ditching runs/waitsFor altogether, and instead do a time based recursive Promise loop, e.g.
function waitUntil(expectF, cond, op) {
var now = new Date().getTime();
function done(actual) {
return cond(actual)
&& new Date().getTime() < now + MAX_WAIT;
}
function loop(promise) {
exports.sleepFor(100); // brief sleep
// Simple recursive loop until condition has been met
return promise
.then(function(response) {
return !done(response)
? loop(op())
: response;
})
.catch(function() {
return loop(op());
});
}
return loop(op())
.then(function(actual) {
expectF(actual);
});
}
op is an operation that returns a Promise.
For example, I wanted to wait until certain number of nodes have joined a cluster:
function waitUntilView(expectNumMembers, nodeName) {
return waitUntil(
function(members) { expect(members.length).toEqual(expectNumMembers); },
function(members) { return _.isEqual(expectNumMembers, members.length); },
getClusterMembers(nodeName)
);
}
I have a small problem, this script works perfectly, with one problem, the "runTenant" method is not returning a promise (that needs resolving from "all()".
This code:
Promise.resolve(runTenant(latest)).then(function() {
end();
});
Calls this code:
function runTenant(cb) {
return new Promise(function() {
//global var
if (!Tenant) {
loadCoreModels();
Tenant = bookshelf.core.bs.model('Tenant');
}
new Tenant().fetchAll()
.then(function(tenants) {
if (tenants.models.length == 0) {
return;
} else {
async.eachSeries(tenants.models, function(tenant, next) {
var account = tenant.attributes;
Promise.resolve(db_tenant.config(account)).then(function(knex_tenant_config) {
if (knex_tenant_config) {
db_tenant.invalidateRequireCacheForFile('knex');
var knex_tenant = require('knex')(knex_tenant_config);
var knex_pending = cb(knex_tenant);
Promise.resolve(knex_pending).then(function() {
next(null, null);
});
} else {
next(null, null);
}
});
});
};
});
});
}
The code from runTenant is working correctly however it stalls and does not proceed to "end()" because the promise from "runTenant(latest)" isn't being resolved.
As if it weren't apparent, I am horrible at promises. Still working on getting my head around them.
Many thanks for any help/direction!
You should not use the Promise constructor at all here (and basically, not anywhere else either), even if you made it work it would be an antipattern. You've never resolved that promise - notice that the resolve argument to the Promise constructor callback is a very different function than Promise.resolve.
And you should not use the async library if you have a powerful promise library like Bluebird at hand.
As if it weren't apparent, I am horrible at promises.
Maybe you'll want to have a look at my rules of thumb for writing promise functions.
Here's what your function should look like:
function runTenant(cb) {
//global var
if (!Tenant) {
loadCoreModels();
Tenant = bookshelf.core.bs.model('Tenant');
}
return new Tenant().fetchAll().then(function(tenants) {
// if (tenants.models.length == 0) {
// return;
// } else
// In case there are no models, the loop iterates zero times, which makes no difference
return Promise.each(tenants.models, function(tenant) {
var account = tenant.attributes;
return db_tenant.config(account).then(function(knex_tenant_config) {
if (knex_tenant_config) {
db_tenant.invalidateRequireCacheForFile('knex');
var knex_tenant = require('knex')(knex_tenant_config);
return cb(knex_tenant); // can return a promise
}
});
});
});
}
Your promise in runTenant function is never resolved. You must call resolve or reject function to resolve promise:
function runTenant() {
return new Promise(function(resolve, reject) {
// somewhere in your code
if (err) {
reject(err);
} else {
resolve();
}
});
});
And you shouldn't pass cb in runTenant function, use promises chain:
runTenant()
.then(latest)
.then(end)
.catch(function(err) {
console.log(err);
});
You need to return all the nested promises. I can't run this code, so this isn't a drop it fix. But hopefully, it helps you understand what is missing.
function runTenant(cb) {
//global var
if (!Tenant) {
loadCoreModels();
Tenant = bookshelf.core.bs.model('Tenant');
}
return new Tenant().fetchAll() //added return
.then(function (tenants) {
if (tenants.models.length == 0) {
return;
} else {
var promises = []; //got to collect the promises
tenants.models.each(function (tenant, next) {
var account = tenant.attributes;
var promise = Promise.resolve(db_tenant.config(account)).then(function (knex_tenant_config) {
if (knex_tenant_config) {
db_tenant.invalidateRequireCacheForFile('knex');
var knex_tenant = require('knex')(knex_tenant_config);
var knex_pending = cb(knex_tenant);
return knex_pending; //return value that you want the whole chain to resolve to
}
});
promises.push(promise); //add promise to collection
});
return Promise.all(promises); //make promise from all promises
}
});
}
I ran into a bug in my code that puzzled me for a long time and am looking for some clarification.
In this code, the commented out inner promise was causing a problem. The Promise.all() at the end was continuing as soon as the setTimeout hit, not after the resolve inside the timeout.
Wrapping the async code with a promise fixes the flow problem, but why is this?
Essentially, why can't we just run normal async code in a .then() chain, an return a Promise.resolve() at the end of the async callback?
var asyncPromise = function() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('Async Promise done');
resolve();
}, 1000);
});
};
var generateSignupPromises = function(qty) {
var promiseArray = [];
for (var i = 1; i <= qty; i++) {
promiseArray.push(
function() {
return asyncPromise()
.then(function() {
console.log('Before Timeout');
//Uncommenting this fixes the issue
//return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('After Timeout');
//resolve();
return Promise.resolve();
}, 500);
//})
});
}
);
}
return promiseArray;
};
var test = generateSignupPromises(1);
Promise.all([test[0]()])
.then(function() {
console.log('Done');
});
Link to running code: http://www.es6fiddle.net/imfdtuxc/
why can't we just run normal async code in a .then() chain, an return a Promise.resolve() at the end of the async callback?
You perfectly can. But any value - be it a promise or whatever - being returned from a plain asynchronous callback is just ignored as usual.
There is nothing that starting the asynchronous action inside a then callback changes about this, setTimeout just doesn't return a promise - and the then won't know about anything asynchronous happening that it could wait for.
If you want to return a promise from a callback and get another promise for that eventual result, it has to be a then callback:
asyncPromise()
.then(function() {
return new Promise(function(resolve, reject) {
// ^^^^^^
setTimeout(resolve, 500);
}).then(function() {
// ^^^^^^^^^^^^^^^
return Promise.resolve();
});
});
Then is a sync function so if you want to do async task inside then, you has to return a Promise.
Also, Promise.all expect an array of promises. Not an array of an array.
var asyncPromise = function() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('Async Promise done');
resolve();
}, 1000);
});
};
var generateSignupPromises = function(qty) {
var promiseArray = [];
for (var i = 1; i <= qty; i++) {
promiseArray.push(
function() {
return asyncPromise()
.then(function() {
console.log('Before Timeout');
//Uncommenting this fixes the issue
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('After Timeout');
resolve();
//return Promise.resolve();
}, 500);
})
});
}
);
}
return promiseArray;
};
var test = generateSignupPromises(1);
Promise.all([test[0]()])
.then(function() {
console.log('Done');
});
http://www.es6fiddle.net/imfe2sze/
I'm playing around with promises and I'm having trouble with an asynchronous recursive promise.
The scenario is an athlete starts running the 100m, I need to periodically check to see if they have finished and once they have finished, print their time.
Edit to clarify :
In the real world the athlete is running on a server. startRunning involves making an ajax call to the server. checkIsFinished also involves making an ajax call to the server. The code below is an attempt to imitate that. The times and distances in the code are hardcoded in an attempt to keep things as simple as possible. Apologies for not being clearer.
End edit
I'd like to be able to write the following
startRunning()
.then(checkIsFinished)
.then(printTime)
.catch(handleError)
where
var intervalID;
var startRunning = function () {
var athlete = {
timeTaken: 0,
distanceTravelled: 0
};
var updateAthlete = function () {
athlete.distanceTravelled += 25;
athlete.timeTaken += 2.5;
console.log("updated athlete", athlete)
}
intervalID = setInterval(updateAthlete, 2500);
return new Promise(function (resolve, reject) {
setTimeout(resolve.bind(null, athlete), 2000);
})
};
var checkIsFinished = function (athlete) {
return new Promise(function (resolve, reject) {
if (athlete.distanceTravelled >= 100) {
clearInterval(intervalID);
console.log("finished");
resolve(athlete);
} else {
console.log("not finished yet, check again in a bit");
setTimeout(checkIsFinished.bind(null, athlete), 1000);
}
});
};
var printTime = function (athlete) {
console.log('printing time', athlete.timeTaken);
};
var handleError = function (e) { console.log(e); };
I can see that the promise that is created the first time checkIsFinished is never resolved. How can I ensure that that promise is resolved so that printTime is called?
Instead of
resolve(athlete);
I could do
Promise.resolve(athlete).then(printTime);
But I'd like to avoid that if possible, I'd really like to be able to write
startRunning()
.then(checkIsFinished)
.then(printTime)
.catch(handleError)
The bug is that you are passing a function that returns a promise to setTimeout. That promise is lost into the ether. A band-aid fix might be to recurse on the executor function:
var checkIsFinished = function (athlete) {
return new Promise(function executor(resolve) {
if (athlete.distanceTravelled >= 100) {
clearInterval(intervalID);
console.log("finished");
resolve(athlete);
} else {
console.log("not finished yet, check again in a bit");
setTimeout(executor.bind(null, resolve), 1000);
}
});
};
But meh. I think this is a great example of why one should avoid the promise-constructor anti-pattern (because mixing promise code and non-promise code inevitably leads to bugs like this).
Best practices I follow to avoid such bugs:
Only deal with async functions that return promises.
When one doesn't return a promise, wrap it with a promise constructor.
Wrap it as narrowly (with as little code) as possible.
Don't use the promise constructor for anything else.
After this, I find code easier to reason about and harder to bugger up, because everything follows the same pattern.
Applying this to your example got me here (I'm using es6 arrow functions for brevity. They work in Firefox and Chrome 45):
var console = { log: msg => div.innerHTML += msg + "<br>",
error: e => console.log(e +", "+ e.lineNumber) };
var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
var startRunning = () => {
var athlete = {
timeTaken: 0,
distanceTravelled: 0,
intervalID: setInterval(() => {
athlete.distanceTravelled += 25;
athlete.timeTaken += 2.5;
console.log("updated athlete ");
}, 2500)
};
return wait(2000).then(() => athlete);
};
var checkIsFinished = athlete => {
if (athlete.distanceTravelled < 100) {
console.log("not finished yet, check again in a bit");
return wait(1000).then(() => checkIsFinished(athlete));
}
clearInterval(athlete.intervalID);
console.log("finished");
return athlete;
};
startRunning()
.then(checkIsFinished)
.then(athlete => console.log('printing time: ' + athlete.timeTaken))
.catch(console.error);
<div id="div"></div>
Note that checkIsFinished returns either athlete or a promise. This is fine here because .then functions automatically promote return values from functions you pass in to promises. If you'll be calling checkIsFinished in other contexts, you might want to do the promotion yourself, using return Promise.resolve(athlete); instead of return athlete;.
Edit in response to comments from Amit:
For a non-recursive answer, replace the entire checkIsFinished function with this helper:
var waitUntil = (func, ms) => new Promise((resolve, reject) => {
var interval = setInterval(() => {
try { func() && resolve(clearInterval(interval)); } catch (e) { reject(e); }
}, ms);
});
and then do this:
var athlete;
startRunning()
.then(result => (athlete = result))
.then(() => waitUntil(() => athlete.distanceTravelled >= 100, 1000))
.then(() => {
console.log('finished. printing time: ' + athlete.timeTaken);
clearInterval(athlete.intervalID);
})
.catch(console.error);
var console = { log: msg => div.innerHTML += msg + "<br>",
error: e => console.log(e +", "+ e.lineNumber) };
var wait = ms => new Promise(resolve => setTimeout(resolve, ms));
var waitUntil = (func, ms) => new Promise((resolve, reject) => {
var interval = setInterval(() => {
try { func() && resolve(clearInterval(interval)); } catch (e) { reject(e); }
}, ms);
});
var startRunning = () => {
var athlete = {
timeTaken: 0,
distanceTravelled: 0,
intervalID: setInterval(() => {
athlete.distanceTravelled += 25;
athlete.timeTaken += 2.5;
console.log("updated athlete ");
}, 2500)
};
return wait(2000).then(() => athlete);
};
var athlete;
startRunning()
.then(result => (athlete = result))
.then(() => waitUntil(() => athlete.distanceTravelled >= 100, 1000))
.then(() => {
console.log('finished. printing time: ' + athlete.timeTaken);
clearInterval(athlete.intervalID);
})
.catch(console.error);
<div id="div"></div>
Using setTimeout / setInterval is one of the scenrios that doesn't play well with promises, and causes you to use the frowned promise anti-pattern.
Having said that, if you reconstruct your function make it a "wait for completion" type of function (and name it accordingly as well), you'd be able to solve your problem. The waitForFinish function is only called once, and returns a single promise (albeit a new one, on top of the original promise created in startRunning). The handling of the recurrence through setTimeout is done in an internal polling function, where proper try/catch is used to ensure exceptions are propagated to the promise.
var intervalID;
var startRunning = function () {
var athlete = {
timeTaken: 0,
distanceTravelled: 0
};
var updateAthlete = function () {
athlete.distanceTravelled += 25;
athlete.timeTaken += 2.5;
console.log("updated athlete", athlete)
}
intervalID = setInterval(updateAthlete, 2500);
return new Promise(function (resolve, reject) {
setTimeout(resolve.bind(null, athlete), 2000);
})
};
var waitForFinish = function (athlete) {
return new Promise(function(resolve, reject) {
(function pollFinished() {
try{
if (athlete.distanceTravelled >= 100) {
clearInterval(intervalID);
console.log("finished");
resolve(athlete);
} else {
if(Date.now()%1000 < 250) { // This is here to show errors are cought
throw new Error('some error');
}
console.log("not finished yet, check again in a bit");
setTimeout(pollFinished, 1000);
}
}
catch(e) { // When an error is cought, the promise is properly rejected
// (Athlete will keep running though)
reject(e);
}
})();
});
};
var printTime = function (athlete) {
console.log('printing time', athlete.timeTaken);
};
var handleError = function (e) { console.log('Handling error:', e); };
startRunning()
.then(waitForFinish)
.then(printTime)
.catch(handleError);
While all this code is functioning properly, a polling solution is never advised in an asynchronous environment and should be avoided if possible. In your case, since this sample mocks communication with a server, I'd consider using web sockets if possible.
Since your use of promises is pretty off the mark, it's a little hard to tell exactly what you're trying to do or what implementation would best fit, but here's a recommendation.
Promises are a one-shot state machine. As such, you return a promise and exactly one time in the future, the promise can be either rejected with a reason or resolved with a value. Given that design of promises, I think what makes sense would be something that can be used like this:
startRunning(100).then(printTime, handleError);
You could implement that with code like this:
function startRunning(limit) {
return new Promise(function (resolve, reject) {
var timeStart = Date.now();
var athlete = {
timeTaken: 0,
distanceTravelled: 0
};
function updateAthlete() {
athlete.distanceTravelled += 25;
console.log("updated athlete", athlete)
if (athlete.distanceTravelled >= limit) {
clearInterval(intervalID);
athlete.timeTaken = Date.now() - timeStart;
resolve(athlete);
}
}
var intervalID = setInterval(updateAthlete, 2500);
});
}
function printTime(athlete) {
console.log('printing time', athlete.timeTaken);
}
function handleError(e) {
console.log(e);
}
startRunning(100).then(printTime, handleError);
Working demo: http://jsfiddle.net/jfriend00/fbmbrc8s/
FYI, my design preference would probably be to have a public athlete object and then methods on that object to start running, stop running, etc...
Here are some of the fundamental things you got wrong in a use of promises:
They are one-shot objects. They are resolved or rejected only once.
The structure startRunning().then(checkIsFinished) just doesn't make logical sense. For the first part of this to work, startRunning() has to return a promise, and it has to resolve ore reject that promise when something useful happens. Your are just resolving it after two seconds which doesn't really seem to accomplish anything useful.
The words of your description make it sound like you want `checkIsFinished() to keep going an not resolve its promise until the athlete is finished. It is possible to do that by continually chaining promises, but that seems a very complicated way to do things and certainly not necessary here. Further, that isn't at all what your code attempts to do. Your code just returns a new promise that is never resolved unless the athelete has already passed the desired distance. If not, it returns a promise that is never resolved or rejected. This is a fundamental violation of promise concepts. A function that returns a promise is responsible for eventually resolving or rejecting it unless the calling code expects to just abandon the promise in which case it's probably the wrong design tool.
Here's another approach that creates a public Athlete() object that has some methods and allows multiple people to be watching the progress:
var EventEmitter = require('events');
function Athlete() {
// private instance variables
var runInterval, startTime;
var watcher = new EventEmitter();
// public instance variables
this.timeTaken = 0;
this.distanceTravelled = 0;
this.startRunning = function() {
startTime = Date.now();
var self = this;
if (runInterval) {clearInterval(runInterval);}
runInterval = setInterval(function() {
self.distanceTravelled += 25;
self.timeTaken = Date.now() - startTime;
console.log("distance = ", self.distanceTravelled);
// notify watchers
watcher.emit("distanceUpdate");
},2500);
}
this.notify = function(limit) {
var self = this;
return new Promise(function(resolve, reject) {
function update() {
if (self.distanceTravelled >= limit) {
watcher.removeListener("distanceUpdate", update);
resolve(self);
// if no more watchers, then stop the running timer
if (watcher.listeners("distanceUpdate").length === 0) {
clearInterval(runInterval);
}
}
}
watcher.on("distanceUpdate", update);
});
}
}
var a = new Athlete();
a.startRunning();
a.notify(100).then(function() {
console.log("done");
});