Promise not executing - javascript

Promise not executing as expected. Not sure what I am doing wrong here, the then after promise all never executes.
exports.handler = (event, database, defaultBucket) => {
if( event.data.val() ){
const { userId, postId } = event.params;
createFolderInTmp(postId);
return event.data.ref.parent.once("value", ((snap) => {
//getpostData data
const postData = snap.val();
var downloadPromises = [];
const images = [];
postData.slides.forEach(slide => {
images.push(slide.value);
});
return Promise.all([
...images.map((image) => {
return downloadImageAsync(image, postId, defaultBucket);
})
])
.then(() => {
//-----NEVER EXECUTES THIS STEP, SIMPLY GOES BLANK HERE----
createAGIF(postData, postId);
return console.log('this completed');
})
.then(() => {
return uploadImageAsync( getLocalGIFFilePath(postId), getDestinationUrl(userId, postId) ,'image/gif',defaultBucket)
})
.then(() => {
return updateShareableUrl(userId, postId, defaultBucket);
});
}));
}else{
console.log('No Data available');
return false;
}
};
Adding related functions
function downloadImageAsync(imageUrl, storyId, bucket){
const tempFilePath = getTempDownloadUrl(storyId, encodeURIComponent(imageUrl));
return bucket.file(imageUrl).download({ destination: tempFilePath});
}
Can someone point out what I am doing wrong here?

I was going about this in the wrong way. The moment event.data.ref.parent.once resolves, the job of this function is done, and whatever I return from inside the callback, does not matter anymore. The function execution stops. The resources are deallocated. It was not until Bergi pointed out of handling errors, but in this case there were no errors.

Related

Promise wont return valid value

I have this test I made just to check an API, but then i tryied to add an URL from a second fetch using as parameter a value obtained in the first fetch and then return a value to add in the first fecth. The idea is to add the image URL to the link. thanks in advance.
function script() {
const url = 'https://pokeapi.co/api/v2/pokemon/?offset=20&limit=20'
const result = fetch(url)
.then( (res)=>{
if(res.ok) {
return res.json()
} else {
console.log("Error!!")
}
}).then( data => {
console.log(data)
const main = document.getElementById('main');
main.innerHTML=`<p><a href='${data.next}'>Next</a></p>`;
for(let i=0; i<data.results.length;i++){
main.innerHTML=main.innerHTML+`<p><a href=${getImageURL(data.results[i].url)}>${data.results[i].name}</a></p>`;
}
})
}
async function getImageURL(imgUrl) {
const resultImg = await fetch(imgUrl)
.then( (res)=> {
return res.json()
})
.then (data => {
console.log(data.sprites.other.dream_world.front_default);
})
return resultImg.sprites.other.dream_world.front_default;
}
In general, don't mix .then/.catch handlers with async/await. There's usually no need, and it can trip you up like this.
The problem is that your fulfillment handler (the .then callback) doesn't return anything, so the promise it creates is fulfilled with undefined.
You could return data, but really just don't use .then/.catch at all:
async function getImageURL(imgUrl) {
const res = await fetch(imgUrl);
if (!res.ok) {
throw new Error(`HTTP error ${res.status}`);
}
const resultImg = await res.json();
return resultImg.sprites.other.dream_world.front_default;
}
[Note I added a check of res.ok. This is (IMHO) a footgun in the fetch API, it doesn't reject its promise on HTTP errors (like 404 or 500), only on network errors. You have to check explicitly for HTTP errors. (I wrote it up on my anemic old blog here.)]
There's also a problem where you use getImageURL:
// Incorrent
for (let i = 0; i < data.results.length; i++) {
main.innerHTML=main.innerHTML+`<p><a href=${getImageURL(data.results[i].url)}>${data.results[i].name}</a></p>`;
}
The problen here is that getImageURL, like all async functions, returns a promise. You're trying to use it as those it returned the fulfillment value you're expecting, but it can't — it doesn't have that value yet.
Instead, you need to wait for the promise(s) youre creating in that loop to be fulfilled. Since that loop is in synchronous code (not an async function), we'd go back to .then/.catch, and since we want to wait for a group of things to finish that can be done in parallel, we'd do that with Promise.all:
// ...
const main = document.getElementById('main');
const html = `<p><a href='${data.next}'>Next</a></p>`;
Promise.all(data.results.map(async ({url, name}) => {
const realUrl = await getImageURL(url);
return `<p><a href=${realUrl}>${name}</a></p>`;
}))
.then(paragraphs => {
html += paragraphs.join("");
main.innerHTML = html;
})
.catch(error => {
// ...handle/report error...
});
For one, your
.then (data => {
console.log(//...
at the end of the promise chain returns undefined. Just remove it, and if you want to console.log it, do console.log(resultImg) in the next statement/next line, after await.
This the final version that accomplish my goal. Just want to leave this just in case someone finds it usefull. Thanks for those who answer!
function script() {
const url = 'https://pokeapi.co/api/v2/pokemon/?offset=20&limit=20'
const result = fetch(url)
.then( (res)=>{
if(res.ok) {
return res.json()
} else {
console.log("Error!!")
}
}).then( data => {
console.log(data)
const main = document.getElementById('main');
main.innerHTML=`<p><a href='${data.next}'>Proxima Página</a></p>`;
Promise.all(data.results.map(async ({url, name}) => {
const realUrl = await getImageURL(url);
return `<div><a href=${realUrl}>${name}</a></div>`;
}))
.then(paragraphs => {
main.innerHTML=main.innerHTML+paragraphs;
})
.catch(error => {
console.log(error);
});
})
}
async function getImageURL(imgUrl) {
const res = await fetch(imgUrl);
if(!res.ok) {
throw new Error(`HTTP Error ${res.status}`)
}
const resultImg = await res.json();
return resultImg.sprites.other.dream_world.front_default
}

How to return a variable along with the promise from a javascript function?

This is where I am stuck:
var verifyEmp = async function () {
return 'Verified';
}
Employee.find(email, password)
.then((emp) => {
console.log(emp);
return verifyEmp();
})
.then((msg) => {
console.log({ verificationMsg: msg });
})
.catch((err) => {
console.log(err);
})
As you can see, verifyEmp is a promise returning function(For demo purposes, I have kept this function as simple as possible). So, what I want to achieve is to be able to log { Emp: emp, verificationMsg: msg } in my second then. How do I pass emp variable in the second then while returning the promise.
I know this is conveniently achievable via async/await. I am just exploring how it can be done using traditional promises.
If you just want to use promises, you can nest a then() into the second one that resolves with the result of the first:
const verifyEmp = async function () {
return 'Verified';
}
const Employee = {
async find() {
return "An employee"
}
}
Employee.find()
.then(emp => verifyEmp().then(msg => [emp, msg]))
.then(([emp, msg]) => {
/* do something with amp and msg */
console.log({emp: emp, verificationMsg: msg });
})
.catch((err) => {
console.log(err);
})
You can return the Promise result from the verifyEmp().then() call (as async functions return a Promise) from the first find().then callback.
There you can pass both the result of the verifyEmp() call and also the emp object from the current scope wrapped in another object to the next then in the chain.
The Promise from the verifyEmp().then() gets automatically unwrapped in the next then callback in the chain:
var verifyEmp = async function () {
return 'Verified';
}
const Employee = {
find: async function(email, password){
return {email, password, "id":123};
}
}
Employee.find("test#abc.com", "test")
.then((emp) => {
//This promise woud get unwrapped in the next .then callback
return verifyEmp()
.then((msg) => ({emp,msg}));
})
.then((msg) => {
console.log(msg);
})
.catch((err) => {
console.error(err);
})
Didn't test it. Use an async iife or something of sort, if you hate anti-patterns. This solution will work regarless of verifyEmp returning a promise or not.
var verifyEmp = async function () {
return 'Verified';
}
Employee.find(email, password)
.then((emp) => {
console.log(emp);
return (async function(){return verifyEmp()})().then((ver)=>[emp,ver]);
})
.then((msg) => {
console.log({ verificationMsg: msg });
})
.catch((err) => {
console.log(err);
})
Just return json object instead of string.
var verifyEmp = async function () {
return 'Verified';
}
Employee.find(email, password)
.then((emp) => {
console.log(emp);
return {emp:emp, msg:verifyEmp()};
})
.then((res) => {
console.log({ Emp: res.emp, verificationMsg: res.msg });
})
.catch((err) => {
console.log(err);
})

Can not return from a function

I have a function that looks like following
export const checkForAvailableAgent = (topicId, serviceUrl, serviceId) => {
const serviceInfo = new window.adiaLive.ServiceInfo({
topicId: topicId, // set here the topicId which you want listen for
OnError: e => {
// react to error message (optional)
console.log("error: ", e);
},
OnServiceStateChange: e => {
if (e.ConnectedAdvisers > 0) {
// there are advisers online for given topicId
console.log("studio available");
return true;
} else {
console.log("studio not available");
return false;
}
}
});
serviceInfo.connect(serviceUrl, serviceId);
};
however the return statements don't return anything when I use the function in the following manner
useEffect(() => {
const agent = checkForAvailableAgent(
`sales_${i18n.language}`,
"https://linktoserviceurl",
"serviceid"
);
// console.log("studio available is: ", agent);
}, []);
the console.log massages appear but the return statement is undefined.
any help would be appreciated.
You can not return from a callback function, as it is running asynchronously and you are not waiting for it to have a result ready.
You can however make the function itself async by returning a Promise instead of the actual result and wait until the Promise has a result ready (e.g. it is resolved):
export const checkForAvailableAgent = (topicId, serviceUrl, serviceId) => {
return new Promise((resolve, reject) => {
const serviceInfo = new window.adiaLive.ServiceInfo({
topicId: topicId, // set here the topicId which you want listen for
OnError: e => {
// react to error message (optional)
console.log("error: ", e);
reject(); // reject on failure
},
OnServiceStateChange: e => {
if (e.ConnectedAdvisers > 0) {
// there are advisers online for given topicId
console.log("studio available");
resolve(true); // resolve instead of return
} else {
console.log("studio not available");
resolve(false);
}
}
});
serviceInfo.connect(serviceUrl, serviceId);
})
};
useEffect(() => {
checkForAvailableAgent(
`sales_${i18n.language}`,
"https://linktoserviceurl",
"serviceid"
).then((agent) => { // then callback is called when the promise resolved
console.log("studio available is: ", agent);
}).catch(error => { // catch is called when promise got rejected
console.log('An error happened');
});
}, []);
The function servceInfo.OnServiceStateChange is a function into the object (seems to be an event).
I'd suggest declaring a variable on the checkForAvailableAgent like connected and change it's value when the event is called.
Then access it using checkForAvailableAgent.connected.
A version with async/await and try/catch
export const checkForAvailableAgent = (topicId, serviceUrl, serviceId) => {
return new Promise((resolve, reject) => {
const serviceInfo = new window.adiaLive.ServiceInfo({
topicId: topicId,
OnError: reject,
OnServiceStateChange: e => resolve(e.ConnectedAdvisers > 0)
});
serviceInfo.connect(serviceUrl, serviceId);
})
};
useEffect(() => {
(async () => {
try {
const isAvailable = await checkForAvailableAgent(
`sales_${i18n.language}`,
"https://linktoserviceurl",
"serviceid"
);
// console.log("Result", isAvailable)
} catch(e) {
console.error(e)
}
})()
// console.log("studio available is: ", agent);
}, []);
There are 2 possible reasons
you are not returning anything from checkForAvailableAgent.
After returning from the checkForAvailableAgent, it might be asynchronous function. You can use async & await.

"A promise was created in a handler but was not returned from it"

When a user clicks on a button (#lfdsubmit), it calls the function (LFD_SearchContainer()) that should return a promise. But the errors happens at
LFD_SearchContainer('EISU1870725')
.then(container => {
ST2.db2(container);
})
What is wrong?
Code: (don't completely trust the commented out parts to guide you through this code -- i forgot to update some of them)
function LFDTrack () {
function LFD_SearchContainer (requestedContainer) {
return new Promise((resolve, reject) => {
let lfd_scanparams = { TableName: 'lfd_table1' }
db.scan(lfd_scanparams, (err, containers) => {
if (err) {
reject(err);
} else {
containers = containers.Items;
let requestedContainers = []; // different variable than arg
let containerObject; // this will be the resolved object
// this will return the object of the searched container
let findIt = _.forEach(containers, container => {
if (container.container === requestedContainer) {
containerObject = container;
}
});
containerObject = findIt[0];
//console.log(findIt[0]);
resolve(containerObject.container);
}
});
});
}
$(function() {
$("#lfdsubmit").click(function (e) {
e.preventDefault();
let lsd_modaltitle = $("#lfdmodaltitle");
let lsd_modalcontent = $("#lfdmodalcontent");
LFD_SearchContainer('EISU1870725')
.then(container => {
ST2.db2(container); // will send the object
})
.catch(error => {
console.log(error);
});
});
});
}
If ST2.db2(container); returns a promise, you need to change that line to
return ST2.db2(container);
If it doesn't, you can put return null; behind it, like this:
ST2.db2(container);
return null;
Since you didn't provide the definition for ST2, I can't know whether or not the db2 method returns a promise. :)
The error is explained by the author of bluebird here.

how to use Q promise with underscore filter

I have found similar questions with different suggestions but I can not get it to work. Some say you can't do it and others give a very long solution to get it working. It is being returned and undefined.
Service
filterSubdivisions: (response) => {
var arry = [];
let deferred = Q.defer();
arry = _.filter(response, (item) => {
if (item.status === 'A') {
item.color = 80;
item.status = 'Active';
return item
} else {
item.color = 255;
item.status = 'Future';
return item
}
});
deferred.resolve(arry);
return deferred.promise;
}
Service Call
AuthService.get().then((result) => {
SubdivisionService.getSubdivisions(result.userId, result.token)
.then((response) => {
if (response)
SubdivisionService.filterSubdivisions(response)
})
.then((res) => {
if (res)
SubdivisionService.loopSubdivisions(res)
})
.then((response) => {
if (response)
StorageService.set('Subdivisions', response)
})
.then(() => me.onGoHome())
.catch(error => {
AlertService.error('subdivisions')
.then((error) => ErrorService.post(error))
.then(() => me.onGoHome())
})
})
I'm not sure why you have filterSubdivisions() returning a promise, especially if you are resolving it right away instead of doing any sort of asynchronous actions. Anyway, you are never attaching a .then() callback to that promise.
You are resolving it with the filtered array, but never have a callback to get that data.

Categories