I have a asynchronous function sayHello() which is called inside greeting() function:
function greeting() {
let P = new Promise();
sayHello().then(function(){
//manipulate DOM
P.resolve();
}).catch(function(error)){
//manipulate DOM
P.reject();
});
return P;
}
I want greeting() to return a promise, so the caller would know when sayHello's work is finished. But this code doesn't seem to be correct, as it says Promise should have resolve and reject functions defined when being constructed. What should I do ?
Just return the Promise returned by sayHello():
function greeting() {
return sayHello().then(function(){
//manipulate DOM
}).catch(function(error)){
//manipulate DOM
});
}
The then method return a Promise.
Here's a simple fiddle illustrating this.
The other answers offer good solutions, but the actual reason you are seeing the error: Promise should have resolve and reject functions defined when being constructed. is the specific Promise implementation you are using. The latest version expects an "executor" function as the first argument when calling it:
new Promise(/* this is the executor: */ function (resolve, reject) { ... });
You can see the specification here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Older versions of Promise did not follow the same specification.
async function greeting() {
let response
try {
response = await sayHello()
} catch(err) {
response = err
}
return response
}
greeting().then(response => console.log(response))
function greeting2() {
return new Promise((resolve, reject) => {
sayHello().then(_ => {
//manipulate DOM
resolve()
}).catch(err => {
//manipulate DOM
reject()
})
})
}
greeting2().then(_ => console.log('something'))
Related
I know this is a common question asked, but I'm having a bit of an issue, trying to fire a function, ONLY when a promise has been returned. I also want to grab the value returned of the promise.
So I want to access an angular service, which seems to make an API call.
Wait for the promise to resolve.
Then store the promise returned as a value.
And then fire the function hello()
It seems when I fire run my code below, validPassengerId and hello()console.logs, before the promise has resolved.
How do I rewrite this code, to:
Wait for promise to resolve.
Then grab the value of the promise resolved - validPassengerId. (And then console.log it).
And then fire the function hello()?
function hello() {
console.log("hello");
};
const promise = new Promise((resolve, reject) => {
let validPassengerId = _funnelBasketLuggageService.FindValidPassengerIdForBag(PassengerIds, bagsAssignedToPassengers, bag);
resolve(validPassengerId);
});
promise.then(validPassengerId => {
console.log("validPassengerId", validPassengerId);
hello();
});
Assuming FindValidPassengerIdForBag returns a promise, you do not need to wrap it in another promise. You would use it like this:
_funnelBasketLuggageService
.FindValidPassengerIdForBag(PassengerIds, bagsAssignedToPassengers, bag)
.then(validPassengerId => {
console.log("validPassengerId", validPassengerId);
hello();
});
If validPassengerId is null with this code, then that must be what FindValidPassengerIdForBag is resolving its promise to. If you weren't expecting that, check the code of FindValidPassengerIdForBag or check that you're passing in valid parameters.
If in fact _funnelBasketLuggageService.FindValidPassengerIdForBag returns a promise, you solve this without creating your own Promise:
function hello() {
console.log("hello");
};
const promise = _funnelBasketLuggageService.FindValidPassengerIdForBag(PassengerIds, bagsAssignedToPassengers, bag);
promise.then(validPassengerId => {
console.log("validPassengerId", validPassengerId);
hello();
});
Explanation What you did was actually wrapping the Promise returned by FindValidPassengerIdForBag in another Promise that returns immediately.
If you absolutely have to wrap it in your own Promise, e.g. because you need to do some preprocessing, use .then instead of the return value of the function:
function hello() {
console.log("hello");
};
const promise = new Promise((resolve, reject) => {_funnelBasketLuggageService.FindValidPassengerIdForBag(PassengerIds, bagsAssignedToPassengers, bag).then(id=>resolve(id));
});
promise.then(validPassengerId => {
console.log("validPassengerId", validPassengerId);
hello();
});
I read that async functions marked by the async keyword implicitly return a promise:
async function getVal(){
return await doSomethingAync();
}
var ret = getVal();
console.log(ret);
but that is not coherent...assuming doSomethingAsync() returns a promise, and the await keyword will return the value from the promise, not the promise itsef, then my getVal function should return that value, not an implicit promise.
So what exactly is the case? Do functions marked by the async keyword implicitly return promises or do we control what they return?
Perhaps if we don't explicitly return something, then they implicitly return a promise...?
To be more clear, there is a difference between the above and
function doSomethingAync(charlie) {
return new Promise(function (resolve) {
setTimeout(function () {
resolve(charlie || 'yikes');
}, 100);
})
}
async function getVal(){
var val = await doSomethingAync(); // val is not a promise
console.log(val); // logs 'yikes' or whatever
return val; // but this returns a promise
}
var ret = getVal();
console.log(ret); //logs a promise
In my synopsis the behavior is indeed inconsistent with traditional return statements. It appears that when you explicitly return a non-promise value from an async function, it will force wrap it in a promise.
I don't have a big problem with it, but it does defy normal JS.
The return value will always be a promise. If you don't explicitly return a promise, the value you return will automatically be wrapped in a promise.
async function increment(num) {
return num + 1;
}
// Even though you returned a number, the value is
// automatically wrapped in a promise, so we call
// `then` on it to access the returned value.
//
// Logs: 4
increment(3).then(num => console.log(num));
Same thing even if there's no return! (Promise { undefined } is returned)
async function increment(num) {}
Same thing even if there's an await.
function defer(callback) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(callback());
}, 1000);
});
}
async function incrementTwice(num) {
const numPlus1 = await defer(() => num + 1);
return numPlus1 + 1;
}
// Logs: 5
incrementTwice(3).then(num => console.log(num));
Promises auto-unwrap, so if you do return a promise for a value from within an async function, you will receive a promise for the value (not a promise for a promise for the value).
function defer(callback) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve(callback());
}, 1000);
});
}
async function increment(num) {
// It doesn't matter whether you put an `await` here.
return defer(() => num + 1);
}
// Logs: 4
increment(3).then(num => console.log(num));
In my synopsis the behavior is indeed inconsistent with traditional
return statements. It appears that when you explicitly return a
non-promise value from an async function, it will force wrap it in a
promise. I don't have a big problem with it, but it does defy normal
JS.
ES6 has functions which don't return exactly the same value as the return. These functions are called generators.
function* foo() {
return 'test';
}
// Logs an object.
console.log(foo());
// Logs 'test'.
console.log(foo().next().value);
Yes, an async function will always return a promise.
According to the tc39 spec, an async function desugars to a generator which yields Promises.
Specifically:
async function <name>?<argumentlist><body>
Desugars to:
function <name>?<argumentlist>{ return spawn(function*() <body>, this); }
Where spawn "is a call to the following algorithm":
function spawn(genF, self) {
return new Promise(function(resolve, reject) {
var gen = genF.call(self);
function step(nextF) {
var next;
try {
next = nextF();
} catch(e) {
// finished with failure, reject the promise
reject(e);
return;
}
if(next.done) {
// finished with success, resolve the promise
resolve(next.value);
return;
}
// not finished, chain off the yielded promise and `step` again
Promise.resolve(next.value).then(function(v) {
step(function() { return gen.next(v); });
}, function(e) {
step(function() { return gen.throw(e); });
});
}
step(function() { return gen.next(undefined); });
});
}
Your question is: If I create an async function should it return a promise or not? Answer: just do whatever you want and Javascript will fix it for you.
Suppose doSomethingAsync is a function that returns a promise. Then
async function getVal(){
return await doSomethingAsync();
}
is exactly the same as
async function getVal(){
return doSomethingAsync();
}
You probably are thinking "WTF, how can these be the same?" and you are right. The async will magically wrap a value with a Promise if necessary.
Even stranger, the doSomethingAsync can be written to sometimes return a promise and sometimes NOT return a promise. Still both functions are exactly the same, because the await is also magic. It will unwrap a Promise if necessary but it will have no effect on things that are not Promises.
Just add await before your function when you call it :
var ret = await getVal();
console.log(ret);
async doesn't return the promise, the await keyword awaits the resolution of the promise. async is an enhanced generator function and await works a bit like yield
I think the syntax (I am not 100% sure) is
async function* getVal() {...}
ES2016 generator functions work a bit like this. I have made a database handler based in top of tedious which you program like this
db.exec(function*(connection) {
if (params.passwd1 === '') {
let sql = 'UPDATE People SET UserName = #username WHERE ClinicianID = #clinicianid';
let request = connection.request(sql);
request.addParameter('username',db.TYPES.VarChar,params.username);
request.addParameter('clinicianid',db.TYPES.Int,uid);
yield connection.execSql();
} else {
if (!/^\S{4,}$/.test(params.passwd1)) {
response.end(JSON.stringify(
{status: false, passwd1: false,passwd2: true}
));
return;
}
let request = connection.request('SetPassword');
request.addParameter('userID',db.TYPES.Int,uid);
request.addParameter('username',db.TYPES.NVarChar,params.username);
request.addParameter('password',db.TYPES.VarChar,params.passwd1);
yield connection.callProcedure();
}
response.end(JSON.stringify({status: true}));
}).catch(err => {
logger('database',err.message);
response.end(JSON.stringify({status: false,passwd1: false,passwd2: false}));
});
Notice how I just program it like normal synchronous particularly at
yield connection.execSql and at yield connection.callProcedure
The db.exec function is a fairly typical Promise based generator
exec(generator) {
var self = this;
var it;
return new Promise((accept,reject) => {
var myConnection;
var onResult = lastPromiseResult => {
var obj = it.next(lastPromiseResult);
if (!obj.done) {
obj.value.then(onResult,reject);
} else {
if (myConnection) {
myConnection.release();
}
accept(obj.value);
}
};
self._connection().then(connection => {
myConnection = connection;
it = generator(connection); //This passes it into the generator
onResult(); //starts the generator
}).catch(error => {
reject(error);
});
});
}
return new Promise(function(resolve, reject {
const to = setTimeout(function(){
});
});
imagine that I want to make sure resources are cleaned up from inside the executor function.
I would like to do something like this:
return new Promise(function(resolve, reject {
const to = setTimeout(function(){
});
this.finally(function(){
clearTimeout(to);
});
});
but this is not a available in a promise executor function.
Is there some way to clean up async resources in a promise executor?
I guess you could clean them up before call resolve/reject, but there are a few cases where that is harder.
Not sure if you need to clear the timeout after it fired but you could try the following:
var someTest = () => {
var t;
var p = new Promise(
(resole)=>{
t = setTimeout(resole,2000)
}
);
p.finally(
()=>console.log(t,clearTimeout(t))
)
return p;
}
someTest();
Or you could try the following:
var someTest = () =>
new Promise(
(resole)=>{
t = setTimeout(resole,2000)
}
).then(
result=>{
//clean up
return result
},
error=>{
//clean up
return Promise.reject(error)
}
);
From inside the promise executor, you can't get access to the promise. It hasn't been assigned yet to anything that your code can reach.
So, you have two options.
You can put your cleanup code outside the executor where you can access the returned promise with p.finally(). You will then have to also keep track of your resources outside the executor also (which is perhaps inconvenient).
You can replace the resolve() and reject() callbacks with your own stub that does your cleanup, then calls the actual resolve() or reject().
You can use a Deferred object which allows you to call resolve/reject from outside the promise executor thus giving you access to p.finally() and resolve() and reject() all in the same scope (which is really the source of the original challenge).
Here's an example of option #2:
return new Promise(function(rv, rj) {
// have to try/catch here because an execption will automatically reject
// without us having seen it
try {
// declare wrappers that should be called by code in this executor
// do not call rv() and rj() directly
function resolve(arg) {
finally();
rv(arg);
}
function reject(arg) {
finally();
rj(arg);
}
// cleanup code that is only ever called once
let finallyCalled = false;
function finally() {
if (!finallyCalled) {
clearTimeout(to);
finallyCalled = true;
}
}
const to = setTimeout(function(){
});
// elsewhere in this executor it should call resolve() or reject()
} catch(e) {
reject(e);
}
});
Here's an example of option #3.
Deferred objects are generally not recommended, but they do give you access to .finally(), resolve() and reject() all in the same scope which does make some things cleaner (like what you're trying to do).
First a simple promise wrapper that gives us a Deferred object:
// can be used as either:
// let d = Promise.Deferred();
// let d = new Promise.Deferred();
// d.then(...)
// d.resolve(x);
// d.finally(...)
Promise.Deferred = function() {
if (!(this instanceof Promise.Deferred)) {
return new Promise.Deferred();
}
let p = this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
this.then = p.then.bind(p);
this.catch = p.catch.bind(p);
this.finally = p.finally.bind(p);
}
Then, you could use it like this:
// usage
function yourFunction() {
let d = new Promise.Deferred();
const to = setTimeout(...);
// other code here that will call d.resolve() or d.reject()
// cleanup code
d.finally(function() {
clearTimeout(to);
});
return d.promise;
}
This OP describes one of the uglier snafus with Promises imo, but this might work:
return new Promise(function(resolve, reject {
const to = setTimeout(function(){
console.error('timed out');
reject('timed out');
});
doSomething(function(err, data){
if(!to._called){
resolve({to, data})
}
});
})
.then(function(v){
clearTimeout(v && v.to);
return v && v.data;
});
the problem with this solution is that callback in the then is called asynchronous, so it might be possible that the timer resolves in the interim? not sure.
New to Promises in serverside (Node js). Here is my question
I have code in FileA.js
incoming_form = client_services.pullForm('vsl_video1.mp4');
incoming_form.resolve().then(function(results) {
return console.log(results);
});
The incoming_form returns a Promise something like this in FileB.js
incoming_form () {
return Promise (function (resp, rej) {
var myArray = ['fudge', 'fgfdgdf'];
return resp(myArray);
});
}
How can I read my 'myArray' value in FileA.js? when I ran my FileA.js, I am getting this error
TypeError: incoming_form.resolve is not a function
I think you may have misunderstood the internal mechanisms by which Promise objects operate. This is how your code should look:
function incoming_form () {
return new Promise (function (resolve, reject) {
resolve(['fudge', 'fgfdgdf']);
});
}
incoming_form().then(function(results){
console.log ("Results" + results");
})
Note how the promise resolves internally, as opposed in a function call. Whenever a promise resolves, operation (and the arguments that the promise resolves with, in this case an array) is deferred to the closest subsequent then() clause.
Hope this clears some things up!
Use response.json() and then to return the value from promise object.
fetch('http://localhost:3100/comments')
.then(response => response.json())
.then(comments => console.log(comments));
I have got a javascript code like this:
function justTesting() {
promise.then(function(output) {
return output + 1;
});
}
var test = justTesting();
I have got always an undefined value for the var test. I think that it is because the promises are not resolved yet..there is a way to return a value from a promise?
When you return something from a then() callback, it's a bit magic. If you return a value, the next then() is called with that value. However, if you return something promise-like, the next then() waits on it, and is only called when that promise settles (succeeds/fails).
Source: https://web.dev/promises/#queuing-asynchronous-actions
To use a promise, you have to either call a function that creates a promise or you have to create one yourself. You don't really describe what problem you're really trying to solve, but here's how you would create a promise yourself:
function justTesting(input) {
return new Promise(function(resolve, reject) {
// some async operation here
setTimeout(function() {
// resolve the promise with some value
resolve(input + 10);
}, 500);
});
}
justTesting(29).then(function(val) {
// you access the value from the promise here
log(val);
});
// display output in snippet
function log(x) {
document.write(x);
}
Or, if you already have a function that returns a promise, you can use that function and return its promise:
// function that returns a promise
function delay(t) {
return new Promise(function(resolve) {
setTimeout(function() {
resolve();
}, t);
});
}
function justTesting(input) {
return delay(100).then(function() {
return input + 10;
});
}
justTesting(29).then(function(val) {
// you access the value from the promise here
log(val);
});
// display output in snippet
function log(x) {
document.write(x);
}
What I have done here is that I have returned a promise from the justTesting function. You can then get the result when the function is resolved.
// new answer
function justTesting() {
return new Promise((resolve, reject) => {
if (true) {
return resolve("testing");
} else {
return reject("promise failed");
}
});
}
justTesting()
.then(res => {
let test = res;
// do something with the output :)
})
.catch(err => {
console.log(err);
});
Hope this helps!
// old answer
function justTesting() {
return promise.then(function(output) {
return output + 1;
});
}
justTesting().then((res) => {
var test = res;
// do something with the output :)
}
I prefer to use "await" command and async functions to get rid of confusions of promises,
In this case I would write an asynchronous function first,
this will be used instead of the anonymous function called under "promise.then" part of this question :
async function SubFunction(output){
// Call to database , returns a promise, like an Ajax call etc :
const response = await axios.get( GetApiHost() + '/api/some_endpoint')
// Return :
return response;
}
and then I would call this function from main function :
async function justTesting() {
const lv_result = await SubFunction(output);
return lv_result + 1;
}
Noting that I returned both main function and sub function to async functions here.
Promises don't "return" values, they pass them to a callback (which you supply with .then()).
It's probably trying to say that you're supposed to do resolve(someObject); inside the promise implementation.
Then in your then code you can reference someObject to do what you want.
I think what the original poster wants is to return an unwrapped value from a promise without actually returning another promise. Unless proven otherwise, I'm afraid this is not possible outside of a then() or async/await context. You always get a promise no matter what.
You need to make use of reference data type like array or object.
function foo(u,n){
let result = [];
const userBrands = new Promise((res, rej)=> {
res(['brand 1', 'brand 3']);
})
userBrands.then((ub)=>{
return new Promise((res, rej) =>{
res([...ub, 'brand 4', 'brand 5']);
})
}).then(response => {
return result.push(...response);
});
return result;
};
foo();
You cannot return value after resolving promise. Instead call another function when promise is resolved:
function justTesting() {
promise.then(function(output) {
// instead of return call another function
afterResolve(output + 1);
});
}
function afterResolve(result) {
// do something with result
}
var test = justTesting();