What is wrong with promise resolving? - arrays

Any ideas? Why does node say 'filename is undefined'? Thanks.
Contract, policy ans invoice functions resolve with no data, just resolve().
var dc = function(data) {
return new Promise(function(resolve, reject) {
var filename = 'Test';
var contract = function() { ... }
var policy = function() { ... }
var invoice = function() { ... }
contract().then(invoice().then(policy().then(function() {
console.log(filename); // Test
resolve(filename); // UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): ReferenceError: filename is not defined
})))
})
}

First of all, you cannot write:
contract().then(invoice() ... )
(that would work if the invoice() function returned another function to act as a then handler)
You have to write:
contract().then(function (value) { invoice() ... })
Or:
contract().then(value => invoice() ... )
Or maybe this if one function should handle the result of other function:
contract().then(invoice).then(policy).then(function (result) { ... });
What you have to pass as an argument to then is a function, not a result of calling a function (which is probably a promise in your example).
I don't know if that's the only problem with your approach but it is certainly one of the problems. Of course it may work but probably not how you expect.
2017 Update
If you use ES2017 async/await that's available in Node since v7.0 then instead of:
contract().then(invoice).then(policy).then((result) => { ... });
you can use:
let a = await contract();
let b = await invoice(a);
let c = await policy(b);
// here your `result` is in `c`
or even this:
let result = await policy(await invoice(await contract()));
Note that you can only use it in functions declared with the async keyword. This works on Node since version 7. For older versions of Node you can use a similar thing with a slightly different syntax using generator-based coroutines, or you can use Babel to transpile your code if that's what you prefer of if that what you already do.
This is quite a new feature but there are a lot of questions on Stack Overflow about it. See:
try/catch blocks with async/await
Do async in a blocking program language way?
try/catch blocks with async/await
Use await outside async
Using acyns/await in Node 6 with Babel
When do async methods throw and how do you catch them?
using promises in node.js to create and compare two arrays
Keeping Promise Chains Readable
function will return null from javascript post/get

It looks like you don't care about the order, in which case you could use Promise.all. Does this work for you? It will resolve once all of the promises have been resolved, or it will reject as soon as any one of them rejects.
function contract(data) { return new Promise(...) }
function policy(data) { return new Promise(...) }
function invoice(data) { return new Promise(...) }
function dc(data) {
var filename = 'Test';
return new Promise(function(resolve, reject) {
Promise.all([contract(data), policy(data), invoice(data)]).then(
function (values) {
console.log(filename);
resolve(filename)
},
function (err) {
reject(err);
}
);
});
}
If you care about the order, then you do have to chain them, like you've tried to do. You're code is passing promises as an argument to then. You need to pass functions.
function contract(data) { return new Promise(...) }
function policy(data) { return new Promise(...) }
function invoice(data) { return new Promise(...) }
function dc(data) {
var filename = 'Test';
return new Promise(function(resolve, reject) {
contract(data).then(
function (contract_res) {
policy(data).then(
function (policy_res) {
invoice(data).then(
function (invoice_res) {
console.log(filename);
resolve(filename);
},
function (err) { reject(err); } // invoice promise rejected
);
},
function (err) { reject(err); } // policy promise rejected
);
},
function (err) { reject(err); } // contract policy rejected
);
});
}
You may be able to simplify this with catch, but the deep nesting is a pain. Take a look at this post about flattening Promise chains.

Related

NextJS Global Variable with Assignment

I'm new to NextJS, and trying to figure out, how to create a global variable that I could assign a different value anytime. Could someone give a simple example? (I know global might not be the best approach, but still I would like to know how to set up a global variable).
Let's say:
_app.js
NAME = "Ana" // GLOBAL VARIABLE
page_A.js
console.log(NAME) // "Ana"
NAME = "Ben"
page_B.js
console.log(NAME) // "Ben"
try using Environment Variables
/next.config.js
module.exports = {
env: {
customKey: 'my-value',
},
}
/pages/page_A.js
function Page() {
return <h1>The value of customKey is: {process.env.customKey}</h1>
}
export default Page
but you can not change its contents, except by changing it directly in next.config.js
Nextjs no special ways to provide global variables you want. You can achieve by:
Stateful management tool, like redux-react
Using Context
It's not like it's impossible,
I created a file called _customGlobals.jsx and put this as content
String.prototype.title = function () {
const sliced = this.slice(1);
return (
this.charAt(0).toUpperCase() +
(sliced.toUpperCase() === sliced ? sliced.toLowerCase() : sliced)
);
};
and imported it in _app.jsx like this:
import "./_customGlobals";
So now I can call this function on any string anywhere in my project like this:
"this is a title".title()
Database designed for this purpose. But for one var it's not wise to install whole db!
So, you can do it in a JSON file.
Add a var to a JSON file and use a function to update it.
this is a simple function for this usage:
const fs = require('fs');
function updateJSONFile(filePath, updates) {
fs.readFile(filePath, 'utf8', function (err, data) {
if (err) {
console.error(err);
return;
}
let json = JSON.parse(data);
for (let key in updates) {
json[key] = updates[key];
}
fs.writeFile(filePath, JSON.stringify(json, null, 2), 'utf8', function (err) {
if (err) {
console.error(err);
}
});
});
}
So, use it like this:
updateJSONFile('file.json', { name: 'John Doe', age: 30 });
You can create another function to read it dynamicly:
function readJSONFile(filePath) {
fs.readFile(filePath, 'utf8', function (err, data) {
if (err) {
return callback(err);
}
let json;
try {
json = JSON.parse(data);
} catch (error) {
return callback(error);
}
return callback(null, json);
});
}
and you can use it like this:
const readedFile = readJSONFile('file.json')
I deleted the callback function to have a simple code but you can add callback function to log error messages.

Angular: use $q.all for optional promise?

I refactored my code have cleaner code without duplication. But I'm wondering if the use of $q.all is the best option in my scenario...
Code logic:
I have an "optional" promise. In 1 scenario I need to call an external API (= promise), in the other scenario, I don't need that external call (= no promise).
So I created a variable in which I can store the promise (or null for the scenario without promise).
$q.all waits for the promise and then checks if the return value is something returned by the promise (scenario 1) or null(scenario 2).
Function before refactor
model.updateWish = function(wish) {
var defer = $q.defer();
if (wish.image) {
// Rename temporary image.public_id to wish_id
cloudinaryService.renameImage(wish.image.public_id, wish._id,
function (image) {
// Update wish with renamed image
wish.image = image;
$http.put(URLS.WISH + "/" + wish._id, wish).success(function (wish) {
updateWishlist(wish);
defer.resolve(wish);
console.info("wish updated", wish);
});
});
} else {
$http.put(URLS.WISH + "/" + wish._id, wish).success(function (wish) {
updateWishlist(wish);
defer.resolve(wish);
console.info("wish updated", wish);
});
}
return defer.promise;
}
Code after refactor
model.updateWish = function(wish) {
var defer = $q.defer();
var renamedImagePromise = null;
if (wish.image) {
// Rename temporary image.public_id to wish_id
renamedImagePromise = cloudinaryService.renameImage(wish.image.public_id, wish._id)
.then( function (image) {
// Update wish with renamed image
wish.image = image;
return wish;
});
}
// Wait until renameImagePromise is resolved and send updated wish to server
$q.all([renamedImagePromise]).then(function(wishWithRenamedImage){
if (wishWithRenamedImage[0]) { // $q.all returns an array, wish is in "wishWithRenamedImage[0]"
wish = wishWithRenamedImage[0];
}
$http.put(URLS.WISH + "/" + wish._id, wish).success(function (wish) {
updateWishlist(wish);
defer.resolve(wish);
console.info("wish updated", wish);
});
})
return defer.promise;
}
Both functions work, but I'm wondering if this is the best implementation for my requirements...
Use $q.when and also avoid the deferred anti-pattern:
model.updateWish = function(wish) {
̶v̶a̶r̶ ̶d̶e̶f̶e̶r̶ ̶=̶ ̶$̶q̶.̶d̶e̶f̶e̶r̶(̶)̶;̶
var renamedImagePromise = null;
if (wish.image) {
// Rename temporary image.public_id to wish_id
renamedImagePromise = cloudinaryService.renameImage(wish.image.public_id, wish._id)
.then( function (image) {
var wishClone = Object.assign({},wish);
// Update wish clone with renamed image
wishClone.image = image;
return wishClone;
});
};
// Wait until renameImagePromise is resolved and send updated wish to server
return $q.when(renamedImagePromise).then(function(wishWithRenamedImage){
var wishToPut = wishWithRenamedImage || wish;
return $http.put(URLS.WISH + "/" + wish._id, wishToPut)
.then(function (resolve) {
var wish = resolve.data;
updateWishlist(wish);
̶d̶e̶f̶e̶r̶.̶r̶e̶s̶o̶l̶v̶e̶(̶w̶i̶s̶h̶)̶;̶
console.info("wish updated", wish);
return wish;
});
});
̶r̶e̶t̶u̶r̶n̶ ̶d̶e̶f̶e̶r̶.̶p̶r̶o̶m̶i̶s̶e̶;̶
};
Update
Out of an abundance of caution, I modified the code to clone the wish object. When an object reference is passed to a JavaScript function, that function can mutate that object. With functional programming best practices, mutating objects should be avoided.

Understanding Promises: Need to combine multiple results

How do I process the results of more than one Promise?
Say the results a of DoA and b of DoB in DoNext
I read https://developer.mozilla.org/de/docs/Web/JavaScript/Guide/Using_promises
It introduces the "then"-Syntax which is supposed to replace the "callback pyramid of doom" however I don't understand the following:
DoA.then(function(a){
return DoB(a)
})
.then(function(b){
DoNext(a,b);
})
In the call of DoNext, a is unknown. I understand that this is because a is only defined in the anonymous function in line 2. However in the "callback pyramid of doom" I can access a, because in that pattern DoNext is within the anonymous function that is the success callback of DoA.
How do I handle this in then-Syntax?
There are multiple ways of handling multiple Promise situation.
1- Chain Promise (ugly though)
DoA.then(a => {
DoB(a).then(.....)
})
.catch(error => console.log(error));
2- Promise.all()
var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then(function(values) {
console.log(values);
});
// expected output: Array [3, 42, "foo"]
3- async function (but read the details)
(async () => {
const a = await DoA(); // DoA must be a Promise
const b = await DoB(a); // DoB must be a Promise
// rest of the code
})();

Angular 7/Typescript : Create queue/array of methods

I have a requirements that some functions should be called after some method completes execution.
Below is my code of processing the queue.
processQueue() {
while (this.queue.length) {
var item = this.queue.shift();
item.resolve(item.func(item.types));
}
}
This is one of the sample function to push method in queue
getAllValues() {
let promise1 = new Promise((resolve, reject) => {
if (this.isReady) {
resolve(this._getAllValues());
} else {
this.queue.push({
resolve: resolve,
func: this._getAllValues
});
}
});
return promise1;
}
And this is one of the function which will be called on processing the queue
_getAllValues() {
var results = {}, values = this.enumInstance.enumsCache.values;
for (var type in values) {
if (values.hasOwnProperty(type)) {
results[type] = values[type][this.enumInstance.lang];
}
}
return results;
}
The issue i am facing is when i call _getAllValues() directly then i am able to access this.enumInstance.
But when same method is being accessed through processQueue() i am unable to access this.enumInstance. It gives me undefined. I think this is not referred to main class in this case.
So can anyone help me here. How can i resolve this?

AngularJS: promise in a loop

I am unable to do the promise looping.
I make a service call to get list of providers, then for each provider, I make another service call to get a customer.
A provider has 1 or more customers. So eventual list of customer is to be decorated and displayed.
In other format I am trying to achieve:
*serviceA.getProvider(){
foreach(providers){
foreach(provider.customerID){
serviceB.getCustomer(customerId)
}
}
}
.then(
foreach(Customer){
updateTheCustomer;
addUpdatedCustomerToAList
}
displayUpdatedCustomreList();
)*
I have written following code, that isn't working
doTheJob(model: Object) {
let A = [];
let B = [];
let fetchP = function(obj) {
obj.Service1.fetchAllP().then(function (response) {
let P = cloneDeep(response.data);
_.forEach(P, function(prov) {
_.forEach(prov.CIds, function(Id) {
A.push(Id);
});
});
_.forEach(A, function(CId) {
return obj.Service2.getById(CId);//what works is if this statement was: return obj.Service2.getById(A[0]);
//So, clearly, returning promise inside loop isn't working
});
})
.then(function(response) {
B.push(response.data); //This response is undefined
angular.forEach(B, function (value) {
obj.updateAdr(value)
});
obj.dispay(B);
});
};
fetchP(this);
}
forEach don't stop when you use return inside of it, try to use a plain loop instead, why you don't just loop with for ?
_.forEach(A, function(CId) {
return obj.Service2.getById(CId);
}
as stated by #Ze Rubeus if you return inside a callback within a for loop that value will be lost, since it's not returned to the caller.
probably you wanted something like this
return Promise.all(A.map(function(CId){
//collect each promise inside an array that will then be resolved
return obj.Service2.getById(CId);
})

Resources