I'm having problmes in finding the use of promises and also admit that my understanding of them is very basic. From what I can tell, they just seem to mimic sync behavior.
Is it possible to use promises and keep the async behaviour then use then() once they have all completed?
Such as this...
var fileRegister = [ 'fileA', 'fileB', 'fileC' ];
for( i in fileRegister ) {
asyncLoadFile( fileRegister[ i ], function( err, data ) {
delete fileRegister[ i ];
if ( ! fileRegister.length ) {
console.log('done');
}
});
}
Yes, you can use Promise.all to wait on multiple promises:
var fileRegister = [ 'fileA', 'fileB', 'fileC' ];
// returns a promise for a file
function loadFile(filename) {
return new Promise(function (resolve, reject) {
asyncLoadFile(filename, function (err, data) {
if (err) {
reject(err);
}
resolve(data);
});
});
}
Promise.all(fileRegister.map(loadFile))
.then(function (files) {
console.log("done");
});
I'm truly surpised there seems to be no authoratative answer for this on the site. Yes, you can create a bunch of promises (each wrapping an async operation) and then call Promise,all which will resolve once they all do:
var p1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 1000, "one");
});
var p2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 2000, "two");
});
var p3 = new Promise(function(resolve, reject) {
setTimeout(resolve, 3000, "three");
});
var p4 = new Promise(function(resolve, reject) {
setTimeout(resolve, 4000, "four");
});
var p5 = new Promise(function(resolve, reject) {
reject("reject");
});
Promise.all([p1, p2, p3, p4, p5]).then(function(value) {
console.log(value);
}, function(reason) {
console.log(reason)
});
This is part of the E^ specification and is supported by most implementations.
Related
So, I have two promises that I want to print on screen with a 3sec delay in between. How would I achieve it. Below is the code.
const promiseOne = new Promise(function(resolve, reject) {
resolve("Hello")
});
const promiseTwo = new Promise(function(resolve, reject) {
resolve("Good Morning")
});
Promise.all([promiseOne, promiseTwo]).then(function() {
setTimeout(() => {
const response = Promise.all.next();
console.log(response);
}, 3000);
});
I suggest you use a delay function. First you loop through each response in the array and use the delay in between
const promiseOne = new Promise(function(resolve, reject) {
resolve("Hello")
});
const promiseTwo = new Promise(function(resolve, reject) {
resolve("Good Morning")
});
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
Promise.all([promiseOne, promiseTwo]).then(async function(resps) {
for(let res of resps){
console.log(res);
await delay(3000)
}
});
const promiseOne = new Promise(function(resolve, reject) {
resolve("Hello")
});
const promiseTwo = new Promise(function(resolve, reject) {
resolve("Good Morning")
});
Promise.all([promiseOne, promiseTwo]).then(function(all) {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(all);
}
, 3000);
});
}).then(console.log)
Return new Promise in then, that promise waits for x millisecond and resolve it.
And do anything in next then
If you just want to delay the log then you can add response parameter as explained by #Daniel RodrÃguez Meza.
But if you want to delay response from any one of the promise promiseOne or promiseTwo then you should use setTimeout(() => resolve("Hello"), 300); inside respective promise as shown below. Also do not use setTimeout inside Promise.All.
As per OP's comment I have updated answer to resolve promiseTwo 3 seconds after promiseOne resolves.
Here I've assigned resolve of promiseTwo to global variable resolvePromiseTwo which is used inside promiseOne to resolve promiseTwo after 3 seconds.
Note I have used .then after promiseOne and promiseTwo just to verify output. You can omit both.
let resolvePromiseTwo = null;
const promiseOne = new Promise(function(resolve, reject) {
resolve("Good Morning")
setTimeout(() => resolvePromiseTwo("Hello"), 3000);
}).then(res => {
console.log('promiseOne resolved');
return res;
});
const promiseTwo = new Promise(function(resolve, reject) {
resolvePromiseTwo = resolve;
}).then(res => {
console.log('promiseTwo resolved');
return res;
});
Promise.all([promiseOne, promiseTwo]).then(function(response) {
console.log('Promise.all');
console.log(response);
});
You were pretty close, you just need to receive the value from the results of the Promise.all and then handle that information, like this:
const promiseOne = new Promise(function(resolve) {
resolve("Hello")
});
const promiseTwo = new Promise(function(resolve) {
resolve("Good Morning");
});
Promise.all([promiseOne, promiseTwo])
.then(function(response) {
setTimeout(() => {
console.log(response);
}, 3000);
});
Edit
According to the clarification given by OP what he needs is the following:
After the first promise is resolved, wait 3 seconds and then execute the second promise.
const promiseOne = new Promise(function(resolve) {
resolve("Hello")
});
const promiseTwo = new Promise(function(resolve) {
resolve("Good Morning");
});
async function resolveWithDelay(delay = 3000) {
const res1 = await promiseOne;
console.log(res1);
setTimeout(async () => {
const res2 = await promiseTwo;
console.log(res2);
}, delay);
}
resolveWithDelay();
I'm trying to execute repeatly multiple processes in sequence by using promise and while (JavaScript/Node.js).
However, the promise function is not executed (i.e., all console.log() is never displayed).
Why is the promise function never executed in the while?
Also, how can I display the some console.log() repeatedly in sequence?
var count = 0;
while(count < 5) {
Promise.resolve()
.then(function () {
return new Promise(function(resolve, reject) {
console.log('func1()...');
resolve('OK');
});
})
.then(function(value) {
return new Promise(function(resolve, reject) {
console.log('func2()...');
resolve('OK');
});
})
.then(function (value) {
console.log('func3()...');
count++;
}).catch(function (error) {
console.log(error);
});
}
.then() still remains an asynchronous callback, see the order of messages here:
Promise.resolve().then(()=>console.log("got resolved"));
console.log("got here");
One thing you can do is wrap the code into an async function:
async function test(){
var count = 0;
while(count < 5) {
await Promise.resolve()
.then(function () {
return new Promise(function(resolve, reject) {
console.log('func1()...');
resolve('OK');
});
})
.then(function(value) {
return new Promise(function(resolve, reject) {
console.log('func2()...');
resolve('OK');
});
})
.then(function (value) {
console.log('func3()...');
count++;
}).catch(function (error) {
console.log(error);
});
}
}
test();
What is happening - in Javascript the event loop and source code you write is executed in one thread. It means that if this one thread is blocked by some work, nothing else is executed.
It works quite straightforward - event loop takes one event (code you show) and it processes ALL synchronous part and it pushes any asynchronous things (the promise chain) to event loop to be executed later.
The issue is this:
var count = 0;
while(count < 5) {
Promise.resolve()
.then(
// some promise chain...
}
The while is catched in never ending loop, as all the synchronous part is that it push this Promise chain in event loop and then starting again. The count is never changed in this context.
The best for you is to use async/await which solves exactly what you want without need deeply understand Node.js
The other option is to use recursion
function promiseChain() {
return Promise.resolve()
.then(function () {
return new Promise(function(resolve, reject) {
console.log('func1()...');
resolve('OK');
});
})
.then(function(value) {
return new Promise(function(resolve, reject) {
console.log('func2()...');
resolve('OK');
});
})
.then(function (value) {
console.log('func3()...');
count++;
}).catch(function (error) {
console.log(error);
});
}
recursivelyExecute(promise, count) {
if (count > 5) {
return;
}
count++;
return promise.then(() => recursivelyExecute(promiseChain(), count+1));
}
var count = 0;
while(count < 5) {
Promise.resolve()
.then(function () {
return new Promise(function(resolve, reject) {
console.log('func1()...');
resolve('OK');
});
})
.then(function(value) {
return new Promise(function(resolve, reject) {
console.log('func2()...');
resolve('OK');
});
})
.then(function (value) {
console.log('func3()...');
}).catch(function (error) {
console.log(error);
});
count++;
}
You need to use Promise.all() along with async.eachSeries for looping. For this you need to install async then do the following:
const async = require('async');
var count = [...Array(5).keys()];
async.eachSeries(count, (c, next) => {
Promise.all([
new Promise(function (resolve, reject) {
console.log('func1()...');
resolve('OK');
}),
new Promise(function (resolve, reject) {
console.log('func2()...');
resolve('OK');
})]).then(function (values) {
console.log('func3()...');
next();
});
}, (err) => {
console.log("here we done");
});
I'm new to Node js Promise I'm not sure whether I'm using the Promise correctly or not so here is my code.
function print(){
first('first')
.then(second('second'))
.then(third('third'));
}
function first(a){
return new Promise((resolve, reject) => {
var res1 = function (){
resolve(a);
}
});
console.log(a);
}
function second(b){
return new Promise((resolve, reject) => {
var res1 = function (){
resolve(b);
}
});
setTimeout(() => {
console.log(b);
}, 2000);
}
function third(c){
return new Promise((resolve, reject) => {
var res1 = function (){
resolve(c);
}
});
console.log(c);
}
My desired output is
first
second
third
Instead what I get is
first
third
//after two seconds
second
I'm missing something but I can't figure it out please explain me
To get the expected behaviour, you need to resolve inside of the timeout (next to the console log). You also cannot pass arguments into promise chain functions since they need to accept the promise from the previous thennable.
A working snippet is below:
print();
function print(){
first('first')
.then(second)
.then(third);
}
function first(a){
return new Promise((resolve, reject) => {
console.log(a);
resolve(a);
});
}
function second(b){
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("second");
resolve(b);
}, 2000);
});
}
function third(c){
return new Promise((resolve, reject) => {
console.log("third");
resolve(c)
});
}
Below outlines a promise that has two simple steps display on the console something, then display something else after the first step is completed.
I am trying to understand how to resolve the promise, and allow the 2nd step to complete.
var lookup_documents = new Promise(
function(resolve, reject) {
console.log("1st");
//resolve(); - How do I do this outside of this function?
}
);
lookup_documents.then(
function() {
console.log("2nd");
}
);
Normally you use new Promise() when you want to wrap some asynchronous function into a promise, such as:
new Promise((resolve, reject) => {
makeAjaxCall((err, data) => {
if(err) return reject(err);
else return resolve(data);
})
});
There are other Promise implementations, such as q, where you can create a "deferred" object that returns a promise... Something similar would be:
function makeAjaxCallPromise() {
let deferred = Q.defer();
makeAjaxCall((err, data) => {
if(err) return deferred.reject(err);
else return deferred.resolve(data);
});
return deferred.promise;
}
For the specific thing you want... All I can think of is declare a variable outside of the promise function scope and asign it, something like:
let resolver, rejecter;
new Promise((resolve, reject) => {
resolver = resolve;
rejecter = reject;
});
makeAjaxCall((err, data) => {
if(err) return resolver(err);
else return rejecter(data);
});
But that doesn't look too good and can lead to errors... Try to wrap everything in your Promise function.
You can do it like this, using your example - if I understand you correctly.
var lookup_documents = function() {
return new Promise(function(resolve, reject) {
console.log("1st");
resolve();
});
};
lookup_documents().then(function() {
console.log("2nd");
});
Hi I'm new to Js and I'd like to wait some async functions complete before print ni. But the code never print it I cannot understand why. Please help me:(
// public function
this.run = function() {
'use strict';
let compile_lib = lib_array.map((item) => {
return new Promise(() => {compileEntry(item);})
});
Promise.all(compile_lib).then(() => { console.log("ni"); });
}
The Promise.all(iterable) method returns a promise that resolves when
all of the promises in the iterable argument have resolved, or rejects
with the reason of the first passed promise that rejects.
In your example, you didn't resolve or reject your Promises:
let compile_lib = lib_array.map((item) => {
return new Promise((resolve, reject) => { compileEntry(item); })
});
please note the arguments resolve, reject. You should use these callbacks either to resolve or reject the promise. For example:
new Promise((resolve, reject) => {
var result = compileEntry(item);
if(result) {
resolve(result);
}else {
reject("reson");
}
})
You need to use resolve and reject
new Promise( /* executor */ function(resolve, reject) { ... } );
var lib_array = [1, 2, 3];
function compileEntry(item, index) {
return new Promise((resolve, reject) => {
setTimeout(function() {
resolve(console.log(item));
}, index * 1000);
});
}
this.run = function() {
'use strict';
let compile_lib = lib_array.map((item, index) => {
return compileEntry(item, index);
});
Promise.all(compile_lib).then(() => {
console.log("ni");
});
}
this.run();