Pass promise to another function in Javascript - javascript

I would like to do something like this
function doSomething(aPromise) {
if (/*xxx*/) {
// doSomethingElse
} else {
return aPromise
.then(doSomethingMore)
}
}
However, if i do this, aPromise will always be executed when calling doSomething. How do i lazy execute it until it get called

Try using aPromise as a function , returning Promise value from calling aPromise() at else block
function aPromise() {
return Promise.resolve(/* `Promise` return value */)
}
function doSomething(aPromise) {
if (/*xxx*/) {
// doSomethingElse
} else {
// call `aPromise()`
return aPromise()
.then(doSomethingMore)
}
}

Related

(Javascript) How to return two promises in one function on different condition

I have a function calc(), which may have following:
calc() {
...
if (condition) {
return new Promise(...) ; // promise1
}
else {
return new Promise(...); // promise2
}
}
The function calls it will act on these two promises differently:
calc().then()=>{ do something; } // if promise 1;
.then()=>{ do nothing; } // if promise 2;
Is it possible to do?
The reason I am asking is that calc() itself is an asynchronous function. It is subscribing to some process like:
calc () {
subscribe(()=> { do something and need to flash upper caller that is done;}
}
so if calc() does not receive signal from another process, it will not yield results, and upper caller does have the necessary data to proceed.
Assuming you know the result of the condition synchronously. Why not wrap the promises in an object and have a property such as id, to denote which promise was returned?
calc() {
...
if (condition) {
return { id: 1, promise: new Promise(...) }; // promise1
}
else {
return { id: 2, promise: new Promise(...) }; // promise2
}
}
You can then decide what to do with the promises based on the id returned.
const result = calc();
if(result.id === 1){
result.then()=>{ do something; } // if promise 1;
}
else if(result.id === 2) {
result.then()=>{ do nothing; } // if promise 2;
}

When is async function promise resolved?

I have below code:
let func = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log("two");
resolve();
}, 3000);
})
};
let func2 = async () => {
console.log("one");
await func();
console.log("three");
}
(async () => {
await func2();
console.log("main"); // This should never be executed
})()
Noticed func2 never returns a value, the promise returned by func2 should never be fullfilled in my opinion. Hence console.log("main") should never be executed. However it is executed after console.log("three"). Can somebody explain this to me?
Noticed func2 never returns a value, the promise returned by func2 should never be fullfilled in my opinion.
That is not how async functions work. Your func2 returns when it is done executing. The return value of a function with no return statement is the specific value undefined. So, undefined becomes the resolved value of the promise. Remember, in Javascript, undefined is a specific value. It's as if you did return undefined at the end of your function block. So, since undefined is the return value, that becomes the resolved value of the async promise.
To fully cover all the bases, async functions always return a promise and that promise gets a resolved/rejected value one of these ways:
1. When you explicitly return a value from the function. That becomes the resolved value of the promise that the async function returns.
async function test() {
return "hello";
}
test().then(val => {
console.log(val); // "hello"
});
2. When you throw an exception. The exception becomes the reject reason of the promise that the async function returns.
async function test() {
throw new Error("ouch");
}
test().catch(err => {
console.log(err); // Shows error object with message "ouch"
});
3. When you return another promise. That promise is chained to the one that the async function returns and the promise that the async function returns will follow the one you returned (resolve when it resolves with the same value or reject with the same reason).
async function test() {
return new Promise(resolve => {
setTimeout(() => {
resolve("hi");
}, 1000);
});
}
test().then(val => {
console.log(val); // "hi"
});
4. When you return nothing. That is the same as in regular functions and it's equivalent to a return undefined at the end of the function block so the resolved value takes on the value of undefined.
So, this:
async function test() {
console.log("hi");
}
test().then(val => {
console.log(val); // undefined
});
Works exactly the same as this:
async function test() {
console.log("hi");
return undefined;
}
test().then(val => {
console.log(val); // undefined
});
A function that does not explexitly return something, actually returns undefined:
function test() { }
console.log(test());
Its the same with async functions, they also resolve to undefined when no other value was returned.
An async function doesn't need a return value in order to resolve. It is considered resolved when it finishes executing without an error.
If you throw new Error() inside of func2, console.log("main") will never be executed.
When you don't return from a function it implicitly returns a default value — normally undefined. So the promise returned by func2 will still resolve when the function returns.
From MDN:
A function without a return statement will return a default value. In
the case of a constructor called with the new keyword, the default
value is the value of its this parameter. For all other functions, the
default return value is undefined.
You can see this in your code if you alter it to this:
(async () => {
func2()
.then(d => console.log(d));
})()

Javascript Nested Promise not run in expected order

I tried to simplify my code, in essence I have this:
function thirdPartyAPIMethod() { // Dummy method returning promise
return Promise.resolve();
}
function func1() {
console.log("func1 start");
return thirdPartyAPIMethod().then(() => {
console.log("func1 end");
// ...
resolve();
});
}
function func2() {
console.log("func2 start");
// ...
console.log("func2 end");
}
func1().then(func2());
I want to run func1 and when it completes then run func2. So I was expecting the output would be this:
func1 start
func1 end
func2 start
func2 end
But instead it prints this:
func1 start
func2 start
func2 end
func1 end
Can someone help me to do this?
Modify your func1 to invoke resolve after thirdPartyAPIMethod's promise has been resolved
function thirdPartyAPIMethod() //dummy method returning promise
{
return Promise.resolve();
}
function func1() {
return new Promise((resolve, reject) => {
console.log("func1 start");
thirdPartyAPIMethod().then( () => {
console.log("func1 end");
resolve(); //invoke resolve here so that func1() is chained with func2
});
});
}
function func2() {
console.log("func2 start");
console.log("func2 end");
}
func1().then( () => func2()); // then has function callback handler instead of return value of func2
In the call to then of the first promise, you're not passing a reference to func2, but calling it:
func1().then(func2()).catch(...);
Change it to:
func1().then(func2).catch(...);
If you want to pass parameters:
func1().then(() => func2(...)).catch(...);
Or, using the pre-ES6 syntax:
funct1().then(function() { return func2(...); }).catch(...);
Besides, when you define the promise you're not calling resolve and reject, so theoretically (except if you haven't posted all your code) that promise never completes:
function func1(...) {
return new Promise((resolve, reject) => {
console.log("func1 start");
thirdPartyAPIMethod().then({
console.log("func1 end");
resolve(''); // resolve the promise with whichever value you want
})
});
}
func1(...).then(func2(...)).catch(...);
in above code func2() is executing before passing as input.
Correct way would be
func1(...).then(func2).catch(...);
P.s the following code is equivalent to what you want to achieve.
thirdPartyAPIMethod().then(func2).catch(...)

How to create a initialization function with promises?

I need a initialization function called only one time for a module. This function is a promise and is called by an execute function. If execute is called twice, the second must wait the initialization then continue the execution.
I wrote this code, but the second call of execute is always waiting and doesn't never return. What have i missed?
var initialized = false;
var initializing = false;
var initializationPromise;
var init = function () {
initializing = true;
return q.promise(function (resolve) {
// simulate initialization
setTimeout(function () {
// initialized
initialized = true;
resolve();
}, 1000);
}).fin(function () {
initializing = false;
});
};
var execute = function () {
return q.promise(function (resolve, reject, notify) {
if (initialized) {
// already initialized
resolve();
} else {
if (!initializing) {
// initializing
initializationPromise = init().then(function () {
// simulate execution
setTimeout(function () {
resolve();
}, 1000);
}, function (reason) {
reject(reason);
});
} else {
// Wait : initializing in progress
return initializationPromise;
}
}
});
};
execute().then(function () {
// This is executed
});
execute().then(function () {
// This is never executed
});
// Wait : initializing in progress
return initializationPromise;
is not correct. That doesn't wait for anything, it just drops out of the q.promise constructor and does not do anything. Also you seem to employ the Promise constructor antipattern.
What you should do instead is
var initialisationPromise = null;
function isInitialised() {
return initialisationPromise != null && initialisationPromise.isFulfilled();
}
function isInitialising() {
return initialisationPromise != null && initialisationPromise.isPending();
}
function init() {
// init can be called as often as necessary, and returns when it's done
if (initialisationPromise == null) { // do the test here!
// this part runs only once
initialisationPromise = q.promise(function (resolve) {
// simulate initialization
setTimeout(function () {
// initialized
resolve();
}, 1000);
});
}
return initialisationPromise;
}
function execute() {
return init().then(function () {
return q.promise(function(resolve, reject, notify) {
// simulate execution
setTimeout(function () {
resolve();
}, 1000);
});
});
}
A resolved/rejected promise will maintain its state (resolved or rejected state), so you can use it to run the initialization code only once. To do that, the init() function should return always the same promise and not create it every time.
For this reason, we create a deferred object (initializationDeferred) outside the init() method and use initializationDeferred to return the same promise every time init() method is called. We need, also, to check if the init() has been already done before, we use the shared variable initializationStarted to skip the setTimeout if already done in a previous invocation.
Now, inside execute you can be sure that the onFulfilled callback of then() is called only when init() method is initialized.
var initializationDeferred = Q.defer(); // Create here the deferred object so it's common to all init() invocations
var initializationStarted = false;
var init = function() {
if (!initializationStarted) {
initializationStarted = true;
setTimeout(function() {
// initialized
console.log('Init timeout fired!');
initializationDeferred.resolve(true); // Resolve the promise associated to the deferred object
}, 1000);
}
return initializationDeferred.promise; // Return the promise associated to the deferred object
};
var execute = function() {
return init().then(function(initialized) {
// Here your module is initialized and you can do whatever you want
// The value of "initialized" here is always "true"
console.log('Execute: initialized?', initialized);
});
};
execute().then(function() {
// This is executed
console.log('Execute First invocation');
});
execute().then(function() {
// This is executed too
console.log('Execute Second invocation');
});
<script src="http://cdnjs.cloudflare.com/ajax/libs/q.js/0.9.2/q.js"></script>

Return JQuery.When deferred resolved

I have a function that include a function to an async function, but I need to return the first one when the async call has been resolved. I'm trying using
return JQuery.when()
The following function is a resume.
function getData(x){
if (x = 1){
return JQuery.when(asynFunction().then(function (data){
(...);
return;
});
}
else {
(...)
return;
}
}
The objective is that getData() doesn't return until the async call has finished.
Any idea?
Thanks for your time!
Assuming that asynFunction() returns a Promise, getData might, at its simplest, look like this :
function getData(x) {
if (x = 1) {
return asynFunction();
}
else {
var myValue = 'whatever';
return myValue;
}
}
However it's often better (though not absolutely necessary) to arrange for a function to return a Promise in all circumstances. This guarantees that wherever getData() is called, the result can be handled in an asynchronous manner (ultimately with .then or .done()) even if it is synchronously derived.
function getData(x) {
if (x = 1) {
return asynFunction();
}
else {
...
var myValue = 'whatever';
return jQuery.when(myValue);
}
}

Categories