I have a function that returns a promise object. This is my code
var foo = function(){
// doSomething() is a promise object
return doSomething().then(() => {
Promise.resolve('Hello');
});
};
foo().then((res) => {
console.log(res);
// res = undefined but not "Hello"
});
I thought function foo would return the promise object and I would get the string "Hello". But I get undefined. Why?
You're missing a return before Promise.resolve, so it should be
var foo = function(){
return doSomething().then(() => {
return Promise.resolve('Hello');
^^^^^^
});
};
However, actually you don't need that at all, and could just return the string Hello.
var foo = function(){
return doSomething().then(() => {
return 'Hello';
});
};
You could make it even simpler by using the concise body form of arrow function, leaving off the {}.
var foo = function(){
return doSomething().then(() => 'Hello');
};
Related
Is it or will it be possible to have an ES6 class getter
return a value from an ES2017 await / async function.
class Foo {
async get bar() {
var result = await someAsyncOperation();
return result;
}
}
function someAsyncOperation() {
return new Promise(function(resolve) {
setTimeout(function() {
resolve('baz');
}, 1000);
});
}
var foo = new Foo();
foo.bar.should.equal('baz');
Update: As others have pointed out, this doesn't really work. #kuboon has a nice workaround in an answer below here..
You can do this
class Foo {
get bar() {
return (async () => {
return await someAsyncOperation();
})();
}
}
which again is the same as
class Foo {
get bar() {
return new Promise((resolve, reject) => {
someAsyncOperation().then(result => {
resolve(result);
});
})
}
}
You can get the value by await on the caller side.
class Foo {
get bar() {
return someAsyncOperation();
}
}
async function test(){
let foo = new Foo, val = await foo.bar;
val.should.equal('baz');
}
You can only await promises, and async functions will return promises themselves.
Of course a getter can yield such a promise just as well, there's no difference from a normal value.
For the value returned by the getter, this changes nothing, since an async function returns a Promise anyway. Where this matters, is in the function, since await can only be used in an async function.
If the issue it that await is wished in the function, I would do:
get property () {
const self = this; // No closure with `this`, create a closure with `self`.
async function f () { // `async` wrapper with a reference to `self`
const x = await self.someFunction(); // Can use `await`
// the rest with “self” in place of “this”
return result;
}
return f(); // Returns a `Promise` as should do an `async get`
}
I was wondering what the best approach is for configuring a module export. "async.function" in the example below could be a FS or HTTP request, simplified for the sake of the example:
Here's example code (asynmodule.js):
var foo = "bar"
async.function(function(response) {
foo = "foobar";
// module.exports = foo; // having the export here breaks the app: foo is always undefined.
});
// having the export here results in working code, but without the variable being set.
module.exports = foo;
How can I export the module only once the async callback has been executed?
edit
a quick note on my actual use-case: I'm writing a module to configure nconf (https://github.com/flatiron/nconf) in an fs.exists() callback (i.e. it will parse a config file and set up nconf).
Your export can't work because it is outside the function while the foodeclaration is inside. But if you put the export inside, when you use your module you can't be sure the export was defined.
The best way to work with an ansync system is to use callback. You need to export a callback assignation method to get the callback, and call it on the async execution.
Example:
var foo, callback;
async.function(function(response) {
foo = "foobar";
if( typeof callback == 'function' ){
callback(foo);
}
});
module.exports = function(cb){
if(typeof foo != 'undefined'){
cb(foo); // If foo is already define, I don't wait.
} else {
callback = cb;
}
}
Here async.function is just a placeholder to symbolise an async call.
In main
var fooMod = require('./foo.js');
fooMod(function(foo){
//Here code using foo;
});
Multiple callback way
If your module need to be called more than once you need to manage an array of callback:
var foo, callbackList = [];
async.function(function(response) {
foo = "foobar";
// You can use all other form of array walk.
for(var i = 0; i < callbackList.length; i++){
callbackList[i](foo)
}
});
module.exports = function(cb){
if(typeof foo != 'undefined'){
cb(foo); // If foo is already define, I don't wait.
} else {
callback.push(cb);
}
}
Here async.function is just a placeholder to symbolise an async call.
In main
var fooMod = require('./foo.js');
fooMod(function(foo){
//Here code using foo;
});
Promise way
You can also use Promise to solve that. This method support multiple call by the design of the Promise:
var foo, callback;
module.exports = new Promise(function(resolve, reject){
async.function(function(response) {
foo = "foobar"
resolve(foo);
});
});
Here async.function is just a placeholder to symbolise an async call.
In main
var fooMod = require('./foo.js').then(function(foo){
//Here code using foo;
});
See Promise documentation
An ES7 approach would be an immediatly invoked async function in module.exports :
module.exports = (async function(){
//some async initiallizers
//e.g. await the db module that has the same structure like this
var db = await require("./db");
var foo = "bar";
//resolve the export promise
return {
foo
};
})()
This can be required with await later:
(async function(){
var foo = await require("./theuppercode");
console.log(foo);
})();
ES6 answer using promises:
const asyncFunc = () => {
return new Promise((resolve, reject) => {
// Where someAsyncFunction takes a callback, i.e. api call
someAsyncFunction(data => {
resolve(data)
})
})
}
export default asyncFunc
...
import asyncFunc from './asyncFunc'
asyncFunc().then(data => { console.log(data) })
Or you could return the Promise itself directly:
const p = new Promise(...)
export default p
...
import p from './asyncModule'
p.then(...)
Another approach would be wrapping the variable inside an object.
var Wrapper = function(){
this.foo = "bar";
this.init();
};
Wrapper.prototype.init = function(){
var wrapper = this;
async.function(function(response) {
wrapper.foo = "foobar";
});
}
module.exports = new Wrapper();
If the initializer has error, at least you still get the uninitialized value instead of hanging callback.
You can also make use of Promises:
some-async-module.js
module.exports = new Promise((resolve, reject) => {
setTimeout(resolve.bind(null, 'someValueToBeReturned'), 2000);
});
main.js
var asyncModule = require('./some-async-module');
asyncModule.then(promisedResult => console.log(promisedResult));
// outputs 'someValueToBeReturned' after 2 seconds
The same can happen in a different module and will also resolve as expected:
in-some-other-module.js
var asyncModule = require('./some-async-module');
asyncModule.then(promisedResult => console.log(promisedResult));
// also outputs 'someValueToBeReturned' after 2 seconds
Note that the promise object is created once then it's cached by node. Each require('./some-async-module') will return the same object instance (promise instance in this case).
Other answers seemed to be partial answers and didn't work for me. This seems to be somewhat complete:
some-module.js
var Wrapper = function(){
this.callbacks = [];
this.foo = null;
this.init();
};
Wrapper.prototype.init = function(){
var wrapper = this;
async.function(function(response) {
wrapper.foo = "foobar";
this.callbacks.forEach(function(callback){
callback(null, wrapper.foo);
});
});
}
Wrapper.prototype.get = function(cb) {
if(typeof cb !== 'function') {
return this.connection; // this could be null so probably just throw
}
if(this.foo) {
return cb(null, this.foo);
}
this.callbacks.push(cb);
}
module.exports = new Wrapper();
main.js
var wrapper = require('./some-module');
wrapper.get(function(foo){
// foo will always be defined
});
main2.js
var wrapper = require('./some-module');
wrapper.get(function(foo){
// foo will always be defined in another script
});
Is there a way to access properties in nested functions like that :
function func(){
this.new_func=function(){
console.log("something");
return 'something';
}
this.someValue=7;
return function(){
return "something_diff";
};
}
var obj=new func();
obj(); //works with returning "something diff"
obj.new_func(); // TypeError: obj.new_func is not a function
obj.someValue; // undefined
I need to delete whole "return function()..." part in order to access "someValue" and "new_func()". Why is it acting like that, and is there a way to somehow access that properties, while still returning another function ??
When you have a constructor that returns an object, that object replaces whatever you assigned to this. So indeed, the members new_func and someValue are lost.
To combine the returned function together with the other members, you can do this:
function func() {
var f = function() {
return "something_diff";
};
f.new_func = function() {
console.log("something");
return 'something';
}
f.someValue = 7;
return f;
}
var obj = new func();
console.log(obj());
obj.new_func();
console.log('someValue:', obj.someValue);
You can do it like this:
var parentFunction = function() {
var nestedFunction = function() {
var value = "nestedValue";
var moreValues = "more values";
return {
value: value,
moreValues: moreValues
}
}
var anotherNestedFunction = function() {
var anotherValue = "nestedValue";
return anotherValue;
}
return {
nested: nestedFunction,
another: anotherNestedFunction
}
}
Then:
var newFunction = new parentFunction();
var nested = newFunction.nested();
console.log("nested value: ", nested.value);
console.log("another nested value: ", newFunction.another);
Here is a working example:
Why is it acting like that, and is there a way to somehow access that properties, while still returning another function ??
Because of the pharenteis:
var obj=new func();
Basically you're firing your function and what is stored the variable obj is what the "func" returns.
In order to access to private properties, you should look at the Closures: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
Looking at the foo function on Bar.prototype:
Bar.prototype.foo = function() {
return console.log("Foo");
};
What's the difference between
Bar = function(name) {
...
this.foo();
};
and
Bar= function(name) {
...
return this.foo(); // note the 'return'
};
The first Bar function returns undefined, which is the default return value of a function in javascript.
The second Bar function returns the result of the this.foo function, which in turn appears to return the result of console.log, which again is undefined.
So they both return undefined, but they do take a different path to get that undefined value.
I'm trying to get this:
a = new Foo(name); // a is function
a(); // returns a result
a.set(); // returns another result
I've implemented above like that:
function Foo (name) = {
val = name;
ret = function () { return val; }
ret.set = function (v) { return val = v; }
return ret;
}
Then, for multiple instances of Foo I'd like not to create method 'set', but share it through prototype property. However, all experiments I did have no effect. It works only on objects, not on functions. Even the code below doesn't work:
foo = function () { return 'a'; }
foo.foo = function () { return 'foo'; }
foo.prototype.bar = function () { return 'bar'; }
foo(); // a
foo.foo(); // foo
foo.bar(); // Uncaught TypeError: Object function () { return 'a'; } has no method 'bar'
Unfortunately there is no way to add a property to only some functions via the prototype chain. Functions have one object in their prototype chain, which is Function.prototype. There is no way to create functions which have other [[Prototype]]s.
The closest you can come to what you want are these two examples:
Your solution
function Foo (name) = {
val = name;
ret = function () { return val; }
ret.set = function (v) { return val = v; }
return ret;
}
Changing Function.prototype
Function.prototype.set = function (v) { return this.val = v; };
function Foo (name){
ret = function () { return this.val; }
ret.val = name;
return ret;
}
var f = new Foo('myfunc');
f.set('myval');
console.log(f.val);
I would strongly recommend the first solution, because in the second one, every function shares the set property/method. Changing predefined Prototypes is usually frowned upon unless it's to port functionality from newer editions of the language.
In your last example foo does not have the function bar, only it's prototype does.
Therefore only a foo object would have the function bar
So you could do this:
foo = function () { return 'a'; }
foo.foo = function () { return 'foo'; }
foo.prototype.bar = function () { return 'bar'; }
var f = new foo(); // [object]
f.foo(); // TypeError: Object [object Object] has no method 'foo'
f.bar(); // bar
Try this:
foo = function (name){
this.name = name;
}
foo.prototype.set = function(name){ return this.name = name; }
var f = new foo('yourName');
alert(f.name);
f.set('yourNameEdited');
alert(f.name);
Here's DEMO