The example of promises and then - javascript

Recently i heard 'promises' and tried to learn how it works and say...
it's not working well.
function example(){
return new Promise(function(){
var i=0;
while(i<5000){console.log(i);i++;}
})
}
example()
.then(
function(){
console.log('done')
},
function(){
console.log('error')
});
it writes 1-4999 but never writes 'done' or 'error'.. how can I make it write 'then' clause?
Your kind reply would be appreciated.

Promises gets two arguments: resolve & reject that will be the functions to be executed as the defined at the .then() & .catch(). So to be able get print the 'done' or 'error' You should do something like this:
function example(condition){
return new Promise(function(resolve, reject){
var i=0;
while(i<5000){console.log(i);i++;}
if(condition){
resolve();
} else {
reject();
}
})
}
example(true).then(function(){console.log('done')},function(){console.log('error')});//Prints 'done'
example(false).then(function(){console.log('done')},function(){console.log('error')});//Prints 'error'

function example() {
return new Promise(function(resolve,reject) {
var i = 0;
while (i < 5000) {
console.log(i);
i++;
}
resolve(i);
})
}
example()
.then(
function() {
console.log('done')
},
function() {
console.log('error')
});
You need resolve, reject callbacks. In your code your Promise always stays in pending state.

Something like... https://www.promisejs.org/patterns/
Ex.:
function example() {
return new Promise(function(resolve, reject){
try{
var i = 0;
while(i < 5000){
console.log('proccess',i);
i++;
}
resolve(i);// an if, to resolve or reject...
} catch(error) {
reject(error);
}
});
}
console.log('will call the promise');
example().then(function(success){
console.log('caller promise result', success);
}).catch(function(error){
console.log('if some problem, catch',error.toString());
});
console.log('Here, will be before or after the promise resolves');

Related

ES6 why does one have to return a promise?

What's the difference between the two (without a return)
function doAsyncTask() {
var promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Async Work Complete");
if (error) {
reject();
} else {
resolve();
}
}, 1000);
});
return promise;
}
The following has no "Return Promise"
function doAsyncTask() {
var promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Async Work Complete");
if (error) {
reject();
} else {
resolve();
}
}, 1000);
});
}
As an extension to Quentin's answer, you should return a promise always.
Idea is, if a function is an async function, it should provide a way to listen to changes. Its upon caller to decide if they need to react to changes.
So you can call your function as:
doAsyncTask().then(...);
or just
doAsyncTask();
But if we do not return promise, caller will never have an option to llisten.
ES6 why does one have to return a promise?
You don't.
What's the difference between the two (without a return)
The difference is that one doesn't return anything.
(So you can't call doAsyncTask and make use of the return value).
var doAsyncTask1 = function() {
var promise = new Promise(resolve => {
/// task that takes 5 seconds
setTimeout(resolve, 5000);
});
return promise;
}
var doAsyncTask2 = function() {
var promise = new Promise(resolve => {
/// task that takes 5 seconds
setTimeout(resolve, 5000);
});
// no return
}
await doAsyncTask1();
console.log('task complete'); // this line of code runs 5 seconds after the previous one
await doAsyncTask2(); // because you have returned nothing, 'await' does nothing
console.log('task2 not complete yet'); // this line of code runs immediately after the previous one, before the 5-second task is complete

Q Promise resolve/reject logic - why isn't promise returned as rejected?

New to promises, trying to understand the logic flow. Thought I understood until I started to insert errors to test. In the example below, when I comment out the 3rd line, why doesn't Reject get returned in the promise?
var Q = require( "q" )
var getInstallBase = function() {
return new Promise(function(resolve, reject) {
//var IBdata = 'temp IBdata'; // <------comment out so IBdata not defined
if (IBdata){
resolve(IBdata); // State will be fulfilled
} else {
reject("error getting IBdata"); // State will be rejected
}
});
}
var mungeIt = function(IBdata){
return new Q.Promise(function(resolve,reject){
// get insight from data
console.log('IBdata = ' + IBdata);
var insight = 'temp insight';
if (insight){
resolve(insight); // State will be fulfilled
} else {
reject("error getting insight"); // State will be rejected
}
})
}
var postResults = function(insight) {
return new Promise(function(resolve, reject) {
console.log('insight = ' + insight);
// post result
var objectID = '12345';
if (objectID){
setTimeout(function() {
console.log('done waiting');
resolve(objectID);
}, 2000);
// State will be fulfilled
} else {
reject("error posting insight to object store"); // State will be rejected
}
});
};
(function extractInsightCycle() {
getInstallBase().then(mungeIt).then(postResults).then(function(objectID) {
console.log('object successfully posted, ID: ' + objectID)
extractInsightCycle();
}).catch(function(error) {
console.log('something went wrong', error);
extractInsightCycle();
})
} )();
Please check out this JSBin: http://jsbin.com/zutotuvomo/edit?js,console
It contains a simplified version of your code, and as you can see, the promise returned from getInstallBase indeed rejects.
Probably something else in your code makes it look like it did not reject.
EDIT:
I took another look at the code, and this is what happens - the rejected promise is being caught by:
function(error) {
console.log('something went wrong', error);
extractInsightCycle();
}
Which calls the extractInsightCycle which is the function that's initiating the whole process, and this causes an infinite loop (endless recursion actually).

One Promise for Multiple Promises - Concurrency Issue

In the method "myMethod" of my "gulpfile.js" I want to create multiple Promises. The quantity depends on the array size (method parameter). When I call the method I want to make sure that all promises are fulfilled before I continue. I would prefer to return not before all promises are fulfilled.
Please have a look at the last five lines of code.
Dependencies
var promiseAll = require('gulp-all');
var del = require('del');
var deleteEmpty = require('delete-empty');
gulp-all | del | delete-empty
Helper Method
var oneForAllPromises = function(promises){
var promAll = promiseAll(promises);
promAll.then(function(param) {
console.log('foo');
}, function(err) {
console.error('foo');
});
return promAll;
}
Problematic Code
var myMethod = function(array1, array2){
var promise = del(array1, {force: true});
promise.then(paths => {console.log('foo');});
var promises = [];
promise.then(()=>{
for(var i=0; i<array2.length; i++){
promises[i] = new Promise(function(resolve, reject) {
deleteEmpty(array2[i], {force: true},
function(err, deleted){
if(err){
console.log('foo');
reject
}else{
console.log('foo');
resolve
}
}
);
});
}
});
// PROBLEM: Returns empty promises array
console.log("promiesesLENGTH: "+promises.length); // promiesesLENGTH: 0
// Create one promise for all the promises
return oneForAllPromises(promises);
}
At the time of the console.log, the first promise promise = del(array1, {force: true}); is not yet finished, so none of the code in the then is yet executed. That's why your promises are empty.
You can simply return in a then another promise:
var myMethod = function(array1, array2){
var promise = del(array1, {force: true});
return promise.then(() => {
return Promise.all(array2.map(array2value => {
return new Promise(function(resolve, reject) {
deleteEmpty(array2value, {force: true}, (err, deleted) => {
if (err) {
reject(err);
} else{
resolve()
}
});
});
}
});
}

Node return BluebirdJS Promise

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
}
});
}

Understanding .then() ES6

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/

Categories