I have a working promise chain:
function startSync(db) {
var promise = new Promise(function(resolve, reject) {
syncCats(db)
.then(syncTrees(db))
.then(syncCars(db))
...
.then(resolve());
});
return promise;
}
This works great. It performs each of those function calls, waiting for each one to complete before firing off another. Each of those functions returns a promise, like so:
function syncCaesar(db) {
var promise = new Promise(resolve, reject) {
// do aysnc db calls, and whatnot, resolving/rejecting appropriately
}
return promise;
}
I need to run this chain on a series of databases, sequentially.
I've tried other solutions here, but they would fire off syncCats() all at once.
For instance:
var promise = Promise.resolve();
dbs.forEach(function(db) {
promise = promise.then(startSync(db));
}
Fires off syncCats(db[0]) and syncCats(db[1]) simultaneously.
Edit:
Performing startSync(dbs[0]).then(startSync(dbs[1])); acts the same.
Edit2: Also performs the same:
dbs.forEach(function(db) {
promise = promise.then(function() {
return startSync(db);
}
}
You're calling startSync and then passing its return value in to then. So naturally, if you do that twice, it's going to start the process twice in parallel.
Instead, pass in a function that doesn't call startSync until it's called:
var promise = Promise.resolve();
dbs.forEach(function(db) {
promise = promise.then(function() { startSync(db); });
});
or with ES2015:
let promise = Promise.resolve();
dbs.forEach(function(db) {
promise = promise.then(_ => startSync(db));
});
Separately, three things jump out about startSync:
It starts all its operations in parallel, not sequentially
It exhibits the promise creation anti-pattern. There's no reason for startSync to create a new promise; it already has a promise it can work with
It ensures that its resolution value is undefined
If you really want the operations running in parallel like that, I suggest being more explicit about it:
function startSync(db) {
return Promise.all([
syncCats(db),
syncTrees(db),
syncCars(db)
])
.then(_ => undefined); // This does #3
}
...but you could also do to avoid the anti-pattern:
// Still run in parallel!
function startSync(db) {
return syncCats(db)
.then(syncTrees(db))
.then(syncCars(db))
.then(_ => undefined); // Does #3
}
If you meant for them to be sequential, you need to pass functions, not the result of calling them:
function startSync(db) {
return syncCats(db)
.then(_ => syncTrees(db))
.then(_ => syncCars(db))
.then(_ => undefined); // Again, does #3
}
If you made syncCats, syncTrees, and syncCars resolve their promises with db, like this:
function syncCats(db) {
return startSomethingAsync().then(_ => db);
}
...then it could be:
function startSync(db) {
return syncCats(db)
.then(syncTrees)
.then(syncCars)
.then(_ => undefined); // Only here for #3
}
...since each would receive db as its first argument.
Finally, if you don't need to force undefined as the promise resolution value, I suggest dropping that part from the above. :-)
With appreciation to T.J and Jaromanda, I was able to solve it by fixing how startSync() was resolved:
function startSync(db) {
var promise = new Promise(function(resolve, reject) {
syncCats(db)
.then(syncTrees(db)) // not correct way to call, see below
.then(syncCars(db))
...
.then(function() { resolve(); });
});
return promise;
}
Now, as T.J points out, the way each of the .then's is being called is incorrect. He explains it better in his answer. I'm being saved by some misunderstood database layer queueing. syncTrees() and syncCars() should be running in parallel.
If I understood it correctly, you will be having an array of databases and you want to sync them one by one i.e. sync for dbs[0], once that is complete sync for dbs[1], and so on. If that's correct you can do something like this.
var syncMultipleDBs = (dataBases) {
var db = dataBases.shift();
if (!db) {
return;
}
startSync(db).then(syncMultipleDBs.bind(null, dataBases));
};
syncsyncMultipleDBs(dbs.slice());
I hope this will help.
Related
In an attempt to understand promises more clearly, i have been reading up a few very interesting articles on the same. I came across the following code which works perfectly for executing promises sequentially. But i am not able to understand how it works.
function doFirstThing(){
return new Promise(function(resolve,reject){
setTimeout(()=>{
resolve(1);
},1000)
})
}
function doSecondThing(res){
return new Promise(function(resolve,reject){
setTimeout(()=>{
resolve(res + 1);
},1000)
})
}
function doThirdThing(res){
return new Promise(function(resolve,reject){
setTimeout(()=>{
resolve(res + 2);
},1000)
})
}
promiseFactories = [doFirstThing, doSecondThing, doThirdThing];
function executeSequentially(promiseFactories) {
var result = Promise.resolve(); // this is the most problematic line
promiseFactories.forEach(function (promiseFactory) {
result = result.then(promiseFactory);// what is happening here ?
});
return result;
}
executeSequentially(promiseFactories)
I do understand that promises are executed as soon as they are created. For some reason i am not able to understand the flow of execution. Especially this following line:
var result = Promise.resolve()//and empty promise is created.
Please if somebody can help me understand how calling the promiseFactory method inside the 'then' method of the empty promise makes it execute sequentially, like so. Or is it because of the forEach loop ?
result = result.then(promiseFactory);
I tried replacing the 'forEach' with a 'map' function and still yielded the same result. i.e, the methods where executed sequentially.
Also, how is the value passed from one chained function to other ?
Any help or article/blog is highly appreciated.
You can image a Promise as a box with execution inside. As far as the promise is created, the execution starts. To get the result value, you have to open the box. You can use then for it:
Promise.resolve(5).then(result => console.log(result)); // prints 5
If you want to chain promises you can do it by opening the box one by one:
Promise.resolve(5)
.then(result => Promise.resolve(result + 1))
.then(result => Promise.resolve(result * 2))
.then(result => console.log(result)); // prints 12
This chaining makes the executions synchronous (one by one).
If you want to execute several promises asynchronously (you don't chain results), you can use Promise.all:
Promise.all([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)])
.then(result => console.log(result)); // prints [1,2,3]
In your case:
Promise.all(promiseFactories).then(result => console.log(result));
Another option how to work with promises is to await them:
(async ()=> {
var res1 = await Promise.resolve(5);
var res2 = await Promise.resolve(res1 + 1);
var res3 = await Promise.resolve(res2 * 2);
console.log(res3); // prints 12
})();
await works similar to then - it makes asynchronous execution to synchronous.
In your case:
async function executeSequentially(promiseFactories) {
for (const p of promiseFactories) {
const result = await p;
console.log(result);
}
}
Note: await packs a value into a Promise out of the box:
var res1 = await 5; // same as await Promise.resolve(5)
The executeSequentially method returns all the Promises one after each other. It happens to iterate over promiseFactory, but it could be written as:
function executeSequentially(promiseFactories) {
return doFirstThing()
.then(() => doSecondThing())
.then(doThirdThing() );
}
It is just the same. We are basically returning a Promise.
Now, however, we want to iterate over a collection of promises.
When iterating, we need to attach the current Promise to the previous with a then. But the forEach does not expose the next Promise -or the previous- in every iteration. And yet we still need it in order to keep chaining Promises one by one. Hence, the result 'hack':
function executeSequentially(promiseFactories) {
var result = Promise.resolve(); /*We need a thing that keeps yelling
the previous promise in every iteration, so we can keep chaining.
This 'result' var is that thing. This is keeping a Promise in every
iteration that resolves when all the previous promises resolve
sequentially. Since we don't have a Promise in the array
previous to the first one, we fabricate one out of 'thin air'
with Promise.resolve() */
promiseFactories.forEach(function (promiseFactory) {
result = result.then(promiseFactory); /* Here result is update
with a new Promise, with is the result of chaining `result`
with the current one. Since `result` already had all the previous ones,
at the end, `result` will be a Promise that depends upon all the
Promises resolution.*/
});
return result;
}
Now, there's also a syntax quirk that maybe is puzzling you:
result = result.then(promiseFactory);
This line is pretty much the same as the following:
result = result.then(resolvedValue => promiseFactory(resolvedValue));
Please if somebody can help me understand how calling the promiseFactory method inside the 'then' method of the empty promise makes it execute sequentially, like so. Or is it because of the forEach loop ?
First thing first, promiseFactory is a pretty bad name there. The method should be better written as follows:
function executeSequentially(promises) {
var result = Promise.resolve(); // this is the most problematic line
promises.forEach(function (currentPromise) {
result = result.then(currentPromise);// what is happening here ?
});
return result;
}
So:
how calling the currentPromise method inside the 'then' method of the empty promise makes it execute sequentially?
It makes execute sequentially because when you attach a Promise to another by then, it executes sequentially. Is a then thing, it is not at all related to the fact that we are iterating over Promises. With plain Promises outside an iteration it works pretty much the same:
Promise.resolve() // fake Promises that resolves instanly
.then(fetchUsersFromDatabase) // a function that returns a Promise and takes
// like 1 second. It won't be called until the first one resolves
.then(processUsersData) // another function that takes input from the first, and
// do a lot of complex and asynchronous computations with data from the previous promise.
// it won't be called until `fetchUsersFromDatabase()` resolves, that's what
// `then()` does.
.then(sendDataToClient); // another function that will never be called until
// `processUsersData()` resolves
It is always recommended to use Promise.all if you want such behaviour:
function doFirstThing() {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(1);
}, 1000)
})
}
function doSecondThing(res) {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(res + 1);
}, 1000)
})
}
function doThirdThing(res) {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(res + 2);
}, 1000)
})
}
let promiseFactories = [doFirstThing(2), doSecondThing(1), doThirdThing(3)];
Promise.all(promiseFactories)
.then(data => {
console.log("completed all promises", data);
})
To run it sequentially one after another:
function doFirstThing() {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(1);
}, 1000)
})
}
function doSecondThing(res) {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(res + 1);
}, 3000)
})
}
function doThirdThing(res) {
return new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(res + 2);
}, 5000)
})
}
promiseFactories = [doFirstThing, doSecondThing, doThirdThing];
function executeSequentially(promiseFactories) {
promiseFactories.forEach(function(promiseFactory) {
promiseFactory(1).then((data) => {
console.log(data)
});
});
}
executeSequentially(promiseFactories);
If we lay out the foreach loop it will look like the following
function doFirstThing(){
return new Promise(function(resolve,reject){
setTimeout(()=>{
console.log(1);
resolve(1);
},1000)
})
}
function doSecondThing(res){
return new Promise(function(resolve,reject){
setTimeout(()=>{
console.log(2);
resolve(res + 1);
},2000)
})
}
function doThirdThing(res){
return new Promise(function(resolve,reject){
setTimeout(()=>{
console.log(3);
resolve(res + 2);
},3000)
})
}
Promise.resolve()
.then(doFirstThing())
.then(doSecondThing())
.then(doThirdThing());
I do understand that promises are executed as soon as they are created. For some reason i am not able to understand the flow of execution. Especially this following line:
var result = Promise.resolve()//and empty promise is created.
This is just to get hold of the promise chain's starting point. Here it is an already resolved promise. To better understand it you can use one of your promises to get hold of the promise chain like below.
let promiseFactories= [doSecondThing, doThirdThing];
let result = doFirstThing();
promiseFactories.forEach(function (promiseFactory) {
result = result.then(promiseFactory);
});
This will also work.
I'm using bluebird and I see two ways to resolve synchronous functions into a Promise, but I don't get the differences between both ways. It looks like the stacktrace is a little bit different, so they aren't just an alias, right?
So what is the preferred way?
Way A
function someFunction(someObject) {
return new Promise(function(resolve) {
someObject.resolved = true;
resolve(someObject);
});
}
Way B
function someFunction(someObject) {
someObject.resolved = true;
return Promise.resolve(someObject);
}
Contrary to both answers in the comments - there is a difference.
While
Promise.resolve(x);
is basically the same as
new Promise(function(r){ r(x); });
there is a subtlety.
Promise returning functions should generally have the guarantee that they should not throw synchronously since they might throw asynchronously. In order to prevent unexpected results and race conditions - throws are usually converted to returned rejections.
With this in mind - when the spec was created the promise constructor is throw safe.
What if someObject is undefined?
Way A returns a rejected promise.
Way B throws synchronously.
Bluebird saw this, and Petka added Promise.method to address this issue so you can keep using return values. So the correct and easiest way to write this in Bluebird is actually neither - it is:
var someFunction = Promise.method(function someFunction(someObject){
someObject.resolved = true;
return someObject;
});
Promise.method will convert throws to rejects and returns to resolves for you. It is the most throw safe way to do this and it assimilatesthenables through return values so it'd work even if someObject is in fact a promise itself.
In general, Promise.resolve is used for casting objects and foreign promises (thenables) to promises. That's its use case.
There is another difference not mentioned by the above answers or comments:
If someObject is a Promise, new Promise(resolve) would cost two additional tick.
Compare two following code snippet:
const p = new Promise(resovle => setTimeout(resovle));
new Promise(resolve => resolve(p)).then(() => {
console.log("tick 3");
});
p.then(() => {
console.log("tick 1");
}).then(() => {
console.log("tick 2");
});
const p = new Promise(resolve => setTimeout(resolve));
Promise.resolve(p).then(() => {
console.log("tick 3");
});
p.then(() => {
console.log("tick 1");
}).then(() => {
console.log("tick 2");
});
The second snippet would print 'tick 3' firstly. Why?
If the value is a promise, Promise.resolve(value) would return value exactly. Promise.resolve(value) === value would be true. see MDN
But new Promise(resolve => resolve(value)) would return a new promise which has locked in to follow the value promise. It needs an extra one tick to make the 'locking-in'.
// something like:
addToMicroTaskQueue(() => {
p.then(() => {
/* resolve newly promise */
})
// all subsequent .then on newly promise go on from here
.then(() => {
console.log("tick 3");
});
});
The tick 1 .then call would run first.
References:
http://exploringjs.com/es6/ch_promises.html#sec_demo-promise
I've had a problem trying to wrap my mind around JavaScript promises. Here is my lately frustration:
var rp = require('request-promise');
function process1000() {
//gets 1000 objects from DB to process
get1000objects()
.then(function (docs) {
Promise.map(docs, addApiData)
})
.then(function (objects) {
console.log(objects)
})
}
function addApiData(element) {
return rp(url).then(function (res) {
resolve(res);
})
.catch(console.error);
}
When rp(url) is called in addApiData(), it doesn't wait until the function is resolved before beginning the next item in the array that I'm passing to Promise.map in process1000(). As soon as rp(url) is called in addApiData, addApiData is called on the next item in the array. The second .then() function in process1000 is then called, prematurely before everything has had a chance to resolve in Promise.map. I've tried a few different libraries to make my GET request but they're all having this same issue. What am I doing wrong here? Any help would be greatly appreciated.
I think you're looking for something more like this:
var rp = require('request-promise');
function process1000() {
//gets 1000 objects from DB to process
get1000objects()
.then(function (docs) {
return Promise.map(docs, addApiData)
})
.then(function (objects) {
console.log(objects);
})
}
function addApiData(element) {
return rp(url)
.catch(console.error);
}
The main point here is that you need to make sure you're returning the promises, or the next then won't know what to do with its value.
Also, try to avoid the Promise constructor antipattern.
In other words, if you return a promise, you don't need to return then as well.
These two are equivalent:
return rp(url).then(function(res) { return res; });
// and
return rp(url);
They both return a promise (rp(url) returns a promise, and rp(url).then( /* ... */) returns a promise).
I'm using bluebird and I see two ways to resolve synchronous functions into a Promise, but I don't get the differences between both ways. It looks like the stacktrace is a little bit different, so they aren't just an alias, right?
So what is the preferred way?
Way A
function someFunction(someObject) {
return new Promise(function(resolve) {
someObject.resolved = true;
resolve(someObject);
});
}
Way B
function someFunction(someObject) {
someObject.resolved = true;
return Promise.resolve(someObject);
}
Contrary to both answers in the comments - there is a difference.
While
Promise.resolve(x);
is basically the same as
new Promise(function(r){ r(x); });
there is a subtlety.
Promise returning functions should generally have the guarantee that they should not throw synchronously since they might throw asynchronously. In order to prevent unexpected results and race conditions - throws are usually converted to returned rejections.
With this in mind - when the spec was created the promise constructor is throw safe.
What if someObject is undefined?
Way A returns a rejected promise.
Way B throws synchronously.
Bluebird saw this, and Petka added Promise.method to address this issue so you can keep using return values. So the correct and easiest way to write this in Bluebird is actually neither - it is:
var someFunction = Promise.method(function someFunction(someObject){
someObject.resolved = true;
return someObject;
});
Promise.method will convert throws to rejects and returns to resolves for you. It is the most throw safe way to do this and it assimilatesthenables through return values so it'd work even if someObject is in fact a promise itself.
In general, Promise.resolve is used for casting objects and foreign promises (thenables) to promises. That's its use case.
There is another difference not mentioned by the above answers or comments:
If someObject is a Promise, new Promise(resolve) would cost two additional tick.
Compare two following code snippet:
const p = new Promise(resovle => setTimeout(resovle));
new Promise(resolve => resolve(p)).then(() => {
console.log("tick 3");
});
p.then(() => {
console.log("tick 1");
}).then(() => {
console.log("tick 2");
});
const p = new Promise(resolve => setTimeout(resolve));
Promise.resolve(p).then(() => {
console.log("tick 3");
});
p.then(() => {
console.log("tick 1");
}).then(() => {
console.log("tick 2");
});
The second snippet would print 'tick 3' firstly. Why?
If the value is a promise, Promise.resolve(value) would return value exactly. Promise.resolve(value) === value would be true. see MDN
But new Promise(resolve => resolve(value)) would return a new promise which has locked in to follow the value promise. It needs an extra one tick to make the 'locking-in'.
// something like:
addToMicroTaskQueue(() => {
p.then(() => {
/* resolve newly promise */
})
// all subsequent .then on newly promise go on from here
.then(() => {
console.log("tick 3");
});
});
The tick 1 .then call would run first.
References:
http://exploringjs.com/es6/ch_promises.html#sec_demo-promise
I just implemented my first function that returns a promise based on another promise in AngularJS, and it worked. But before I decided to just do it, I spent 2 hours reading and trying to understand the concepts behind promises. I thought if I could write a simple piece of code that simulated how promises worked, I would then be able to conceptually understand it instead of being able to use it without really knowing how it works. I couldn't write that code.
So, could someone please illustrate in vanilla JavaScript how promises work?
A promise is basically an object with two methods. One method is for defining what to do, and one is for telling when to do it. It has to be possible to call the two methods in any order, so the object needs to keep track of which one has been called:
var promise = {
isDone: false,
doneHandler: null,
done: function(f) {
if (this.isDone) {
f();
} else {
this.doneHandler = f;
}
},
callDone: function() {
if (this.doneHandler != null) {
this.doneHandler();
} else {
this.isDone = true;
}
}
};
You can define the action first, then trigger it:
promise.done(function(){ alert('done'); });
promise.callDone();
You can trigger the action first, then define it:
promise.callDone();
promise.done(function(){ alert('done'); });
Demo: http://jsfiddle.net/EvN9P/
When you use a promise in an asynchronous function, the function creates the empty promise, keeps a reference to it, and also returns the reference. The code that handles the asynchronous response will trigger the action in the promise, and the code calling the asynchronous function will define the action.
As either of those can happen in any order, the code calling the asynchronous function can hang on to the promise and define the action any time it wants.
For the simplicity to understand about the promises in Javascript.
You can refer below example. Just copy paste in a new php/html file and run.
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
function test(n){
alert('input:'+n);
var promise = new Promise(function(fulfill, reject) {
/*put your condition here */
if(n) {
fulfill("Inside If! match found");
}
else {
reject(Error("It broke"));
}
});
promise.then(function(result) {
alert(result); // "Inside If! match found"
}, function(err) {
alert(err); // Error: "It broke"
});
}
</script>
</head>
<body>
<input type="button" onclick="test(1);" value="Test"/>
</body>
</html>
Click on Test button,
It will create new promise,
if condition will be true it fulfill the response,
after that promise.then called and based on the fulfill it will print the result.
In case of reject promise.then returns the error message.
Probably the simplest example of promises usage looks like that:
var method1 = (addings = '') => {
return new Promise(resolve => {
console.log('method1' + addings)
resolve(addings + '_adding1');
});
}
var method2 = (addings = '') => {
return new Promise(resolve => {
console.log('method2' + addings)
resolve(addings + '_adding2');
});
}
method1().then(method2).then(method1).then(method2);
// result:
// method1
// method2_adding1
// method1_adding1_adding2
// method2_adding1_adding2_adding1
That's basic of basics. Having it, you can experiment with rejects:
var method1 = (addings = '*') => {
return new Promise((resolve, reject) => {
console.log('method1' + addings)
resolve(addings + '_adding1');
});
}
var method2 = (addings = '*') => {
return new Promise((resolve, reject) => {
console.log('method2' + addings)
reject();
});
}
var errorMethod = () => {
console.log('errorMethod')
}
method1()
.then(method2, errorMethod)
.then(method1, errorMethod)
.then(method2, errorMethod)
.then(method1, errorMethod)
.then(method2, errorMethod);
// result:
// method1*
// method2*_adding1
// errorMethod
// method2*
// errorMethod
// method2*
As we can see, in case of failure error function is fired (which is always the second argument of then) and then next function in chain is fired with no given argument.
For advanced knowledge I invite you here.
please check this simple promise code. this will help you to better understand of promise functionality.
A promise is an object that may produce a single value some time in the future: either a resolved value, or a reason that it’s not resolved. A promise may be in one of 3 possible states: fulfilled, rejected, or pending. Promise users can attach callbacks to handle the fulfilled value or the reason for rejection.
let myPromise = new Promise((resolve, reject)=>{
if(2==2){
resolve("resolved")
}else{
reject("rejected")
}
});
myPromise.then((message)=>{
document.write(`the promise is ${message}`)
}).catch((message)=>{
document.write(`the promise is ${message}`)
})
check this out