Call a function inside resolve - javascript

I'm studying promises; can anybody explain me why this piece of code does not work is I call the
function add() inside the resolve?
<script>
async function f() {
function add() {
return 14+3;
}
let promise = new Promise((resolve, reject) => {
setTimeout(()=>{resolve(add)}, 3000); //this doesn't work
setTimeout(()=>{resolve(14+3)}, 3000); // this works
});
let result = await promise;
alert(result);
alert ("END");
}
f();
</script>

When you resolve with value you actually returning value from promise. In your example you resolve with function in arguments, so your promise returns function(function add)
So modify line,
resolve(add);
to
resolve(add());

Related

How does Async/await work and why does it not work here

I've been trying to understand how async/await works, all I want to do is have it wait until the value is returned. However, I could not get it to do so with callbacks nor promises nor async/await. What am I doing wrong, and why does async/await not work as I expect it to? (wait with running other code until this promise is resolved)
Many questions like this one link to "introduction pages". I've read them all, I understand what they do, I just don't know how to properly write them out, as I believe I did everything correctly, I'm just missing something
console.log("xcdcxcxcxccxvccvffdgfcd");
thing();
async function thing() {
let c = await otherthing();
console.log("dfasfadsfdasasdfa" + c)
}
async function otherthing() {
await setTimeout(function() {
return new Promise((resolve, reject) => {
let f = "rerewwqfewfasgsadf"
return resolve(f);
})
}, 3000);
}
console.log is supposed to wait until the promised value c is returned, however, it does not seem to work. Why?
Async/await works with functions that return promises. Your otherthing function doesn't return anything.
You can fix the code by returning the promise you are instantiating, like this:
thing();
async function thing() {
let c = await otherthing();
console.log("dfasfadsfdasasdfa" + c)
}
function otherthing() {
return new Promise((resolve, reject) => {
setTimeout(function () {
let f = "rerewwqfewfasgsadf"
resolve(f);
}, 3000)
});
}
You must return the new Promise from the otherthing function, not from the setTimeout callback. You are supposed to construct the promise, in its executor callback start the asynchronous action (setTimeout) and then asynchronously resolve() or reject() the promise.
function otherthing() {
return new Promise((resolve, reject) => {
setTimeout(function(){
let f = "rerewwqfewfasgsadf"
resolve(f);
}, 3000);
});
}
You don't need any async/await here for the function that is essentially only a promise wrapper around setTimeout. See also How do I convert an existing callback API to promises?.
You should move setTimeout inside Promise body and there do resolve(f)
function otherthing() {
return new Promise((resolve, reject) => {
setTimeout(() => {
let f = "rerewwqfewfasgsadf"
resolve(f);
}, 3000);
});
}
async function otherthing has no return statement, so it will always return a promise that resolves to undefined.
await setTimeout(...) doesn't make any sense. You can only await a promise, and setTimeout does not return a promise.
You need to explicitly:
create a new Promise() inside otherthing
resolve() it with the desired value inside the callback function you pass to setTimeout
return the promise from otherthing
Don't create a promise inside the callback function you pass to setTimeout. It is pointless there.

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(...)

Override Promise constructor and its methods

I want to override the Promise constructor and the then method in Promise.
So, whenever someone creates a new Promise object, first my code will be executed and then the original promise constructor will get called.
Similarly, when someone calls .then function of Promise, first my code will get executed and then the callback of then function will get executed.
I tried this
var bind = Function.bind;
var unbind = bind.bind(bind);
function instantiate(constructor, args) {
return new (unbind(constructor, null).apply(null, args));
}
var oldProto = Promise.prototype;
Promise = function() {
console.log("Promise instantiated");
var promise = instantiate(Promise, arguments);
return promise;
};
Promise.prototype = oldProto;
While calling this using
var myFirstPromise = new Promise((resolve, reject) => {
setTimeout(function(){
resolve("Success!"); // Yay! Everything went well!
}, 250);
});
myFirstPromise.then((successMessage) => {
console.log("Yay! " + successMessage);
});
It led to infinite loop with console filled up with Promise instantiated log. I also tried the following:
Promise = function(Promise) {
MyPromise.prototype = Promise.prototype;
function MyPromise(){
console.log("Hello");
var promise = Function.prototype.bind.apply(MyPromise, arguments);
console.log(promise);
return promise;
}
}(Promise);
But, I am not sure whether the constructor overriden is the correct way to do it and how to define the then function for Promise.

return a promise from .apply method

I'm new to promises and trying to wrap my head around something that should be simple. Maybe someone can hit me in the head with it instead!
I've got these two functions:
//an arbitrary method that runs on delay to mimic an async process
method1 = function( _value, _callback ){
setTimeout(function(){
console.log('dependency1_resolved');
_callback.apply(this, [{valIs:_value}]);
}.bind(this), (Math.random() * 1000));
};
//something that can simple return the object
function returnVal(x){
console.log(x); //this logs 'Object {valIs: 4}'
return x;
}
due to it's async nature, I'd like to run this function in a promise to be used later (maybe even chain later) in my code.
here is my promise:
var promise = new Promise(
function(resolve, reject) {
var x = method1(4, returnVal);
resolve(x);
}
);
promise.then(function(val) {
console.log(val); // undefined
return val;
});
console.log(promise); //Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: undefined}
Does this have anything to do with the .apply method in the first function? What am I missing? Can someone please slap me?
Your returnVal callback doesn't actually do anything.
Instead, you need to actually pass a callback that accepts the value:
var promise = new Promise(
function(resolve, reject) {
method1(4, function(x) { resolve(x); });
}
);
You can also just pass resolve itself as the callback:
var promise = new Promise(
function(resolve, reject) {
method1(4, resolve);
}
);
Your method1 does return nothing, that's why x is undefined. That the returnVal callback does return something is insignificant, its return value is simply ignored by method1.
You will need to call resolve as the callback to make your code work:
new Promise(
function(resolve, reject) {
var x = method1(4, resolve);
}
).then(function(val) {
console.log(val); // undefined
return val;
});
See also How do I return the response from an asynchronous call?

Categories