im trying to write a promise but seems to be missing something. here is my code:
const myPromise = new Promise(() => {
setTimeout(() => {
console.log("getting here");
return setinputs({ ...inputs, images: imageAsUrl });
}, 100);
});
myPromise
.then(() => {
console.log("getting here too");
firebase.database().ref(`collection/${idNode}`).set(inputs);
})
.then(() => {
console.log("all is set");
})
.catch((err) => {
console.log(err);
});
if i run the program, the first part of the promise is executing but all .then() functions arent executing. how do i fix this?
In this scheme, the promise callback has one (resolve) or two (resolve,reject) arguments.
let p = new Promise((resolve, reject)=> {
//do something
//resolve the promise:
if (result === "ok") {
resolve(3);
}
else {
reject("Something is wrong");
}
});
p.then(res => {
console.log(res); // "3"
}).catch(err => {
console.error(err); //"Something is wrrong
});
Of course, nowadays you can use async + await in a lot of cases.
You need to resolve the promise, using resolve() and also return the promise from firebase so the next .then in the chain works properly.
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("getting here");
// You have to call resolve for all `.then` methods to be triggered
resolve({ ...inputs, images: imageAsUrl });
}, 100);
});
myPromise
.then((inputs) => {
console.log("getting here too");
// You have to return a promise in a .then function for the next .then to work properly
return firebase.database().ref(`collection/${idNode}`).set(inputs);
})
.then(() => {
console.log("all is set");
})
.catch((err) => {
console.log(err);
});
Related
i have a promise chain
If i receive error in getServiceCost I want to repeat the chain again (retry) for 2 times how can i achieve this when using Promise chain , meaning again execute getUser, getServiceCost
getUser(100)
.then(getServices)
.then(getServiceCost)
.then(console.log);
function getUser(userId) {
return new Promise((resolve, reject) => {
console.log('Get the user from the database.');
setTimeout(() => {
resolve({
userId: userId,
username: 'admin'
});
}, 1000);
})
}
function getServices(user) {
return new Promise((resolve, reject) => {
console.log(`Get the services of ${user.username} from the API.`);
setTimeout(() => {
resolve(['Email', 'VPN', 'CDN']);
}, 3 * 1000);
});
}
function getServiceCost(services) {
return new Promise((resolve, reject) => {
console.log(`Calculate the service cost of ${services}.`);
setTimeout(() => {
resolve(services.length * 100);
}, 2 * 1000);
});
}
If i receive error in getServiceCost I want to repeat the chain again (retry) for 2 times how can i achieve this when using Promise chain , meaning again execute
getUser, getServiceCost
I'd use an async function (all modern environments support them, and you can transpile for obsolete environments), which lets you use a simple loop. Perhaps as a utility function you can reuse:
async function callWithRetry(fn, retries = 3) {
while (retries-- > 0) {
try {
return await fn();
} catch (error) {
if (retries === 0) {
throw error;
}
}
}
return new Error(`Out of retries`); // Probably using an `Error` subclass
}
Using it:
callWithRetry(() => getUser(100).then(getServices).then(getServiceCost))
.then(console.log)
.catch(error => { /*...handle/report error...*/ });
Or
callWithRetry(async () => {
const user = await getUser(100);
const services = await getServices(user);
return await getServiceCost(services);
})
.then(console.log)
.catch(error => { /*...handle/report error...*/ });
As I understand it, an async function always returns a Promise, which resolves when the function returns, or rejects if an error is thrown.
What happens if an async function returns a Promise on its own? How should this be handled when calling the download() function below?
const download = async () => {
const res = await axios({
"...",
method: 'GET',
responseType: 'stream'
});
const writer = fs.createWriteStream(absoluteArchivePath);
res.data.pipe(writer);
return new Promise((resolve, reject) => {
writer.on('finish', () => resolve());
writer.on('error', () => reject());
})
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
The Promise object represents the eventual completion (or failure) of
an asynchronous operation and its resulting value.
const myAsyncFunction = error => {
return new Promise((resolve, reject) => {
if (error) {
reject('an error occured');
} else {
resolve('OK');
}
});
};
myAsyncFunction(true)
.then(r => {
console.log('ok');
})
.catch(err => {
console.log('error');
});
// log: error
myAsyncFunction(false)
.then(r => {
console.log('ok');
})
.catch(err => {
console.log('error');
});
// log: ok
Im playing around with promises and i wanted a way of rejecting the promise inside of a then callback. So this is done by either calling throw return or return Promise.reject();. So far so good. You can accomplish this by also calling new Promise.reject(); withou a return.
Can someone explain why does this work?
new Promise((res, rej) => {
setTimeout(() => {
res(200);
}, 2000);
})
.then(() => {
console.log("ok1");
new Promise.reject();
// return Promise.reject();
.then(() => {
console.log("ok2");
})
.catch(() => {
console.log("error");
});
new Promise.reject()
Your code throws an exception. Exceptions cause promises to be rejected.
Because Promise.reject is not a constructor, this code works fine:
new Promise((res, rej) => {
setTimeout(() => {
res(200);
}, 2000);
})
.then(() => {
console.log('ok1')
Promise.reject('error!')
})
.then(() => {
console.log("ok2");
})
.catch(() => {
console.log("error");
});
New Promise.reject throws an error so the code jumps to the catch section with the following error : Promise.reject is not a constructor
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 2000);
}).then((res) => {
console.log(res);
new Promise.reject();
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log('error' ,err.message);
});
I have this following piece of code
new Promise((resolve, reject) => {
resolve(apiRequest(data))
reject(console.log('Error'))
}).then(response)
Both methods (resolve and reject) are being fired but I want to call reject only when something goes wrong.
How can I throw an error if something goes wrong on that case?
I checked that but it seems like I can not use an If statement to do that check.
new Promise((resolve, reject) => {
const printResult = apiRequest(data)
console.log(printResult) //Outputs Promise {<pending>}
resolve(printResult) //Then it works
reject(console.log('Error'))
}).then(response)
What would be the correct approach to reject a promise?
The easiest way would be with an if condition. i.e
new Promise((resolve, reject) => {
// do something...
if(somethingGoodHappened) {
resolve(data)
} else {
reject(error)
}
})
But usually when dealing with async requests, the thing you are calling will often be returning a promise, so you can attach the then and catch callbacks there.
apiRequest(data)
.then((result) => {
// all good
})
.catch((err) => {
console.log(err)
})
const mock_api = () => new Promise((res, rej) => {
const number = Math.floor((Math.random() * 100) + 1);
setTimeout(() => {
if (number%2==0) return res('randomly RESOLVED')
return rej('randomly REJECTED')
}, 2000)
})
const async_promise = () => new Promise(async (resolve, reject) => {
try {
const resolvedPromise = await mock_api()
resolve(resolvedPromise)
} catch (e) {
reject(e)
}
})
const classicPromise = () => new Promise((resolve, reject) => {
mock_api()
.then(resolve)
.catch(reject)
})
const makeAsyncRequest = async () => {
try {
const data = await async_promise()
console.log('ASYNC AWAIT RESOLVE', data)
} catch (e) {
console.log('ASYNC AWAIT ERR', e)
}
}
makeAsyncRequest()
classicPromise()
.then(r => console.log('PROMISE CHAIN RESOLVE', r))
.catch(e => console.log('PROMISE CHAIN ERR', e))
Because of you resolve before reject so it cannot run into reject,
You can use:
if (printResult) {
resolve(printResult)
} else {
reject(console.log('Error'))
}
You can catch exceptions and return them as rejected Promises
function asyncFunc() {
try {
doSomethingSync();
return doSomethingAsync()
.then(result => {
ยทยทยท
});
} catch (err) {
return Promise.reject(err);
}
}
Always check for err if there is any err return a promise (example below)
// Return new promise
return new Promise(function(resolve, reject) {
// Do async job
request.get(options, function(err, resp, body) {
if (err) {
reject(err);
} else {
resolve(JSON.parse(body));
}
})
})
I have a situation where I think the only choice for me is to nest some Promises within each other. I have a Promise that needs to be performed and a method that does something until that Promise is complete. Something like this:
let promise = new Promise((resolve, reject) => {
// Do some stuff
});
doSomethingUntilPromiseisDone(promise);
However, within my Promise, I need to execute another method that returns another Promise:
let promise = new Promise((resolve, reject) => {
fetchValue(url)
.then((value) => {
// Do something here
}).catch((err) => {
console.error(err);
});
});
doSomethingUntilPromiseisDone(promise);
But now, in the fetchValue method's then statement, I have another method I need to execute that, guess what, returns another Promise:
let promise = new Promise((resolve, reject) => {
fetchValue(url)
.then((value) => {
saveToCache(value)
.then((success) => {
console.log('success!!');
resolve('success');
});
}).catch((err) => {
console.error(err);
});
});
doSomethingUntilPromiseisDone(promise);
So in the end, I have a Promise, within a Promise, within a Promise. Is there someway I can structure this better so that it is more straightforward? It seems like nesting them within each other is counter to Promise's intended chaining approach.
Use .then()
let doStuff = (resolve, reject) => {/* resolve() or reject() */};
let promise = new Promise(doStuff);
doSomethingUntilPromiseisDone(
promise
.then(value => fetchValue(url))
.then(value => value.blob())
.then(saveToCache)
)
.then(success => console.log("success!!"))
.catch(err => console.error(err))
you can use generator to flatten your nested promises (Bluebird.couroutine or Generators)
//Bluebird.couroutine
const generator = Promise.coroutine(function*() {
try {
const value = yield fetchValue(url);
const success = yield saveToCache(value);
console.log('success:', success);
} catch(e) {
console.error(err);
}
}));
generator();
Each function will call the next one with the result of the method before.
var promises = [1,2,3].map((guid)=>{
return (param)=> {
console.log("param", param);
var id = guid;
return new Promise(resolve => {
// resolve in a random amount of time
setTimeout(function () {
resolve(id);
}, (Math.random() * 1.5 | 0) * 1000);
});
}
}).reduce(function (acc, curr, index) {
return acc.then(function (res) {
return curr(res[index-1]).then(function (result) {
console.log("result", result);
res.push(result);
return res;
});
});
}, Promise.resolve([]));
promises.then(console.log);