Wait for async function to end - javascript

I have the following function that works fine, except I need to wait until it finishes to execute the next statement:
zohoAuth.zoho_oAuth = function () {
// return new Promise((resolve, reject) => {
zohoAuth.state = utils.uuid();
const url = zohoAuth.authorizationURL();
zohoAuth.popUp(url);
getAuthCodeFromCatalyst();
//setTimeout(getAuthCodeFromCatalyst,1000);
function getAuthCodeFromCatalyst() {
return new Promise(function (resolve, reject) {
(async function waitForFoo() {
const gotAuthState = await zohoAuth.getUserDataFromStorageState(zohoAuth.state)
await gotAuthState;
if (gotAuthState) return resolve();
setTimeout(waitForFoo, 1000);
})();
});
}
console.log("bottom of zoho auth")
return true;
// });
}
I call the function with this:
zohoAuth.zoho_oAuth();
console.log("done waiting");
How do i wait for this to finish?

You're making this harder on yourself. Make sure to avoid the explicit promise constructor anti-pattern -
zohoAuth.zoho_oAuth = function () {
zohoAuth.state = utils.uuid();
const url = zohoAuth.authorizationURL();
zohoAuth.popUp(url);
return zohoAuth.getUserDataFromStorageState(zohoAuth.state);
}
You can access the result by attaching a .then handler to the result of your function call -
zohoAuth.zoho_oAuth()
.then(authState => console.log("bottom of auth state", authState))
.catch(console.error)
If you want to use async and await, go ahead. If an error occurs, don't catch it. Instead allow it to bubble up and be handled by the caller -
async function doAuth (...) {
const authState = await zohoAuth.zoho_oAuth()
console.log("received auth state", authState)
return "done" // or whatever
})
doAuth().then(console.log, console.error)

You should consider awaiting on the promise. Below snippet shows the difference of using await -
const asyncFunction = function() {
return new Promise(function(resolve, reject) {
setTimeout(() => {
console.log('inside promise');
resolve();
}, 100);
});
}
function callWithoutAwait() {
asyncFunction();
console.log('after without await function');
}
callWithoutAwait();
async function callWithAwait() {
await asyncFunction();
console.log('after with await function');
}
callWithAwait();

I was able to accomplish what I needed below is the code. Thanks for the help!
zohoAuth.zoho_oAuth = function() {
zohoAuth.state = utils.uuid();
const url = zohoAuth.authorizationURL();
zohoAuth.popUp(url);
return new Promise(function (resolve, reject) {
(async function waitForFoo() {
const gotAuthState = await zohoAuth.getUserDataFromStorageState(zohoAuth.state)
await gotAuthState;
if (gotAuthState) return resolve();
setTimeout(waitForFoo, 1000);
})();
});
}
And this is the call:
zohoAuth.zoho_oAuth()
.then(authState => console.log("bottom of auth state", authState))
.catch(console.error)

Related

resolve promise after setTimeout inside promise

I would like to resolve my promise after my setTimeout will be finished. I have a few functions like step The main idea is to get step results sequentially. P.S. we can't mutate setTimeout.
function step (done) {
return new Promise((resolve, reject) => {
try {
setTimeout(done, 5100, 'hello world')
resolve()
} catch (error) {
reject()
}
})
}
If you can't mutate the setTimeout remove it. Instead of putting the setTimeout in the step function create a new delay function that returns a promise. You can then use async/await to walk through the steps after certain delays.
function delay(time = 1000) {
return new Promise(res => {
setTimeout(() => res(), time);
});
}
function step(fn, n) {
fn(`hello world ${n}`);
}
const fn = (str) => console.log(str);
async function main() {
step(fn, 1);
await delay(5000);
step(fn, 2);
await delay(3000);
step(fn, 3);
}
main();
If you can change the done function, you can do like below.
function step(done) {
return new Promise((resolve, reject) => {
immutableFunc(done(resolve, reject));
});
}
function immutableFunc(done) {
setTimeout(done, 1000, "hello world");
}
function done(resolve, reject) {
return arg => {
try {
console.log(arg);
resolve();
} catch (error) {
reject(error);
}
};
}
async function test() {
try {
await step(done);
await step(done);
await step(done);
} catch (err) {
console.log(err);
}
}
test();

Resolve promise after callback it's executed

I have the following code on which I am trying to block the execution of the method _saveAddress multiple time, so I made a promise for this method.
const [pressEventDisabled, setPressEventDisabled] = useState(false);
<TouchableOpacity style={style.button_container} activeOpacity={1} disabled={pressEventDisabled} onPress={async () => {setPressEventDisabled(true); await _saveAddress(); setPressEventDisabled(false);}} >
The problem is that I want to resolve the promise after the callback method it's executed. It's there any way to wait for the dispatch function to execute or to resolve the promise inside the callback method?
This is the method for saving the address:
const _saveAddress = () => new Promise(async (resolve) => {
var valid = _validate();
if (valid) {
const address = createAddressJson();
if (addressId) {
var addressIdProperty = {
id: addressId
};
const newAddress = Object.assign(addressIdProperty, address);
dispatch(editAddress(newAddress, _onAddressSaveEditCallback));
} else {
dispatch(addAddress(address, _onAddressSaveEditCallback));
}
} else {
//notify
notifyMessage(strings.fill_required_inputs_validation);
resolve();
}
});
This is the callback method:
const _onAddressSaveEditCallback = async (success: boolean, apiValidations: any, address ? : Address, ) => {
if (success) {
if (typeof callback == 'function') {
callback(address);
}
await Navigation.pop(componentId);
} else {
setDataValidations(apiValidations);
}
};
Just do exactly what you say in the title. Nothing more, nothing less:
if (addressId) {
var addressIdProperty = {id: addressId};
const newAddress = Object.assign(addressIdProperty, address);
dispatch(editAddress(newAddress, async (s,v,a) => {
await _onAddressSaveEditCallback(s,v,a);
resolve();
}));
} else {
dispatch(addAddress(address, async (s,v,a) => {
await _onAddressSaveEditCallback(s,v,a);
resolve();
}));
}
Of course, since you are passing async () => {} to addAddress instead of _onAddressSaveEditCallback you have to call _onAddressSaveEditCallback yourself since addAddress will be calling the async () => ...
But mixing promises and callbacks like this isn't great. It leads to weird looking and sometimes confusing code. A better solution is to promisify addAddress:
function addAddressPromise (address) {
return new Promise((resolve, reject) => {
addAddress(address, (success, validations, address) {
if (success) return resolve(address);
else reject(validations)
});
});
}
Now you can wait for addAddress:
const _saveAddress = async () => {
// Don't create new promise here, we do it in addAddress..
// ...
let result = await addAddressPromise(address);
dispatch(result);
await _onAddressSaveEditCallback();
// ...
}

how do I create a nameless async function - Nodejs

I was wondering if it's possible to create a nameless function with the quick functional notation on javascript. What I mean by changing this:
var lobby = ((io) => {
...
}
return {
getWhiteBoardId: (name2, time2, role2, pass2, need_id) => {
let promise = new Promise((res, rej) => {
setTimeout(() => res("Now it's done!"), 1000)
});
// wait until the promise returns us a value
let result = await promise;
}
})(io);
I then want to later be able to call this function:
whiteboardId = lobby.getWhiteBoardId(req.body.name, req.body.time, req.body.role, req.body.pass, need_id);
to have something at the beginning such as this:
var lobby = (async (io) => {
so that I can call my Promise and await
// defining io, to execute the code, you not need to write the next line
const io = {};
const lobby = ((io) => {
// some pre-existing code
return {
// you are using await in this method so add async to the method signature
getWhiteBoardId: async (...args) => {
let promise = new Promise((resolve, reject) => {
setTimeout(() => resolve(args), 1000)
});
// wait until the promise returns us a value
let result = await promise;
// ... some other code/logic as needed
// i have assumed you need to return the result
return result;
}
}
})(io);
// TEST: calling getWhiteBoardID method
lobby.getWhiteBoardId("Hi", "There").then(console.log);
// or
(async () => {
const res = await lobby.getWhiteBoardId("Hello World")
console.log(res);
})();
console.log("First!");

Delay Mocha test programmatically

I'm familiar with Mocha's support of delaying the root suite to enable performing asynchronous operations before a test is executed, by use of running Mocha with the --delay flag, but this impacts all tests.
Is it possible to do something like this on a test by test basis, without using the --delay flag?
An example of a working asynchronous test is below, but unfortunately not of all of our tests are async and call run(). Please note that the below example also leverages dynamically generating tests to generate a test for each URL that is detected during the asynchronous operation before the suite executes.
driver = await new Builder().forBrowser('chrome').build();
await driver.get('http://example.org');
await driver.findElements(By.css('article header a')).then(async function (anchors) {
Promise.all(
anchors.map(async anchor => {
return new Promise(async function (resolve, reject) {
try {
const href = await anchor.getAttribute('href');
urls.push(href);
resolve();
} catch (err) {
console.log('Catch')
reject(err);
}
})
})
).then(function () {
driver.quit();
describe('my suite', function () {
urls.forEach(function (url) {
it(`Loads ${url}`, async function () {
await driver.get(url);
await driver.getTitle().then(function (title) {
assert.strictEqual(1, 1);
});
});
});
});
run();
})
});
Following #destroyer's suggestion, I was successful in accomplishing something similar using asynchronous hooks (below), but cannot dynamically generate a separate test for each URL since Mocha does not delay the root suite execution.
describe('Async test suite', function () {
const getAnchors = function () {
return new Promise(async (resolve) => {
driver = await new Builder().forBrowser('chrome').build();
await driver.get('http://example.org');
await driver.findElements(By.css('article header a'))
.then(async (anchors) => {
resolve(anchors);
})
});
}
const getUrls = function (anchors) {
return new Promise(async resolve => {
for (i = 0; i < anchors.length; i++) {
urls.push(await anchors[i].getAttribute('href'));
if (i === (anchors.length - 1)) {
resolve(urls);
}
}
});
}
const iterateUrls = function (urls) {
return new Promise(async (resolve, reject) => {
for (i = 0; i < urls.length; i++) {
await driver.get(urls[i])
const thisUrl = await driver.getCurrentUrl();
try {
await assert.strictEqual(thisUrl, urls[i]);
} catch (err) {
reject(err);
break;
}
if (i === (urls.length - 1)) {
resolve();
}
}
})
}
async function asyncController() {
Promise.all([
anchors = await getAnchors(),
await getUrls(anchors)
])
}
// Trigger async functions here
before(function (done) {
asyncController()
.then(() => {
done();
})
});
// Close the browser after test completes
after(async function () {
await driver.quit()
});
describe('Checks URLs', function () {
it('Iterates over URLs', async function (done) {
try {
await iterateUrls(urls);
} catch (err) {
done(err);
}
});
});
});

Nested Promises, And Another After Completion [duplicate]

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

Categories

Resources