Node Promise with Local Variable - promise

async function A(){
const x = await B(); // reads a file or such thing
return x; // returns a promise
}
var foo;
function setFoo(){
foo = A(); // foo will be set to the promise returned by A()
// but I really want foo to be set to the data
// returned by the promise
}
function C(){
// here I need to use the value of the data returned
// by the promise. There are dozens of functions that
// will use foo. Those dozens of functions are called
// from outside of this module
}
Question - Is there some way to extract the data from the promise so I can use it in a local variable? Or do I need to use promise semantics i.e .then(function(...){...}) in every function like function C that needs to use the local variable foo? Or something else?

Don't use async in a function that does nothing other than return await. Just return the promise and you're done.
function A() {
return B(); // reads a file or such thing, returns a promise
}
Never try to set global/outer-scope variables to capture asynchronous values. Keep returning the promises, chain in worker functions with .then(). Keep returning the promise chain.
function foo(){
return A().then(C);
}
The worker functions (an event handler, really) receive the data:
function C(data) {
// here you get the data returned by B()
}
You could even wait for C() now:
foo().then(function (x) {
// `C()` ans finished and `x` will be whatever `C()` returned.
})

Related

How to chain completables with closures in RxSwift?

I would like to do something like
Completable.empty()
.andThen { // this does not work
// run some code
NSLog("Now pushing objects")
return Completable.empty // e.g. return api.pushObjects() -> Completable
}
.andThen(Completable.empty()) // this is working
.andThen { // this does not work
// do something else
NSLog("Now pulling objects")
return Completable.empty // e.g. return api.pullObjects() -> Completable
}
andThen (or concat) does not allow closures as argument. The compiler complains:
Trailing closure passed to parameter of type 'Completable' (aka 'PrimitiveSequence<CompletableTrait, Never>') that does not accept a closure
My question is: How to chain completables with closures?
You don't. There is no version of andThen that takes a closure. The closest you can get to it is this:
Completable.empty()
.andThen(Completable.create(subscribe: { observer in
print("Now pushing objects")
observer(.completed)
return Disposables.create()
}))

Does promise object always need callback function?

I have a requirement that I need to create a service in Angular 1 and load data with an API call which can be accessed in controllers. I earlier tried by making a API call with $http service and assigning the data to the variable / object. I then injected the service and assigned the variable / object to the controller scope variable / object.
What I observed in the controller event loop is not same as service event loop and controller scope variable / object remains undefined. Later I got a solution to work by returning a promise from the service, and calling the promise in the controller, however I'm new to promises and not able to fully absorb that when I called a promise, I had to pass the function as argument which I think is a callback for the $http API call, but I'm uncertain how it's working under the hood. Can someone explain it?
//service code
this.getuserimages = function(uname) {
console.log("Username in UserImage Service: " + uname);
var promise = $http.get('/api/images/' + uname).then(function(response) {
this.userimages = response.data;
return this.userimages;
});
return promise;
}
// controller code
var userimagespromise = userImageService.getuserimages($routeParams.username);
userimagespromise.then(function(data) {
$scope.userimages = data;
Your code is a Promise chain.
I rewrited your code in a way that this chain is more clear, but the meaning is exactly the same:
$http.get('/api/images/' + uname)
.then(function(response) {
this.userimages = response.data;
return this.userimages;
})
.then(function(images) {
$scope.userimages = images;
});
You can read this flow in this way:
Please get me user images
And then, we they will be available (=> returned from the get and passed to the then function), save them in a variable and return them to the next element of the chain
And then, we they will be available (=> return from the previous promise), set them in the $scope
Please note that the entire flow is asynchronous because every Promise is "an object representing the eventual completion or failure of an asynchronous operation".
You can find more information in the Promise documentation.

Outputting Value of Promise during multiple parses

I am loading a promise from d3.csv and then making multiple changes to the returned array in subsequent .then calls.
I need to out put to the html (Angular 2) the sate of the array before each change, I can do this using the ( variable | async ) but it will update with each change and I need to output the state before each change.
I tried to clone the promise, but all clones just point to the same promise. Any variables are out of scope in the changes, and the parent scope is not reachable.
data = d3.csv promise
data.then(methodB()). // HTML | async Output Required of Array before changes
then(methodB()) // HTML | async Output Required of Array before changes
etc..
etc..
etc..
(There are around 15 methods applied to the data as it is munched and analyzed)
What is the best way to achieve this?
Assuming :
you have a starting promise named csvPromise, which delivers array
the methods to be applied are methodA, methodB, methodC etc, each of which accepts Array
each method either returns a mutation of the input array or delivers the mutation via a Promise
changes to the array are cumulative, method-on-method
you have a synchronous function output() which will accept the original array and each mutation
then a pattern like this will do the job :
csvPromise
.then(function(arr) {
output(arr); // observe initial array as delivered by csvPromise
return methodA(arr);
})
.then(function(arr) {
output(arr); // observe array after application of methodA
return methodB(arr);
})
.then(function(arr) {
output(arr); // observe array after application of methodB
return methodC(arr);
})
etc..
etc..
etc..
.then(function(arr) {
output(arr); // observe array after application of final method
}).catch(function(error) {
console.log(error); // any error thrown from anywhere in the chain will arrive here
});
The pattern can be proceduralised by building the chain dynamically as follows :
var methods = [methodA, methodB, methodC, ...]; // list of methods (uncalled at this point)
return methods.reduce(function(promise, method) {
return promise.then(function(arr) {
output(arr); // observe result of previous stage
return method(arr);
});
}, csvPromise)
.then(function(arr) {
output(arr); // observe array after application of final method
}).catch(function(error) {
console.log(error); // any error thrown from anywhere in the chain will arrive here
});
The most likely violation of the assumptions would be that output() was itself asynchronous, in which case :
var methods = [methodA, methodB, methodC, ...]; // list of methods
return methods.reduce(function(promise, method) {
return promise.then(function(arr) {
return output(arr).then(function() {
return method(arr);
});
});
}, csvPromise)
.then(function(arr) {
output(arr); // observe array after application of final method
}).catch(function(error) {
console.log(error); // any error thrown from anywhere in the chain will arrive here
});

how do I test a class in mocha?

In my journey towards TDD, I am using Mocha, chai and sinon.
There certainly is a learning curve there.
My goal is to write a test to verify that method4 was executed. How do I achieve that ?
//MyData.js
class MyData {
constructor(input) {
this._runMethod4 = input; //true or false
this.underProcessing = this.init();
}
method1() { return this.method2() }
method2() {
if (this._runMethod4) {
return this.method4();
} else {
return this.method3();
}
method4(){
return thirdPartyAPI.getData();
}
method3(){
return someAPI.fetchData();
}
init(){
return this.method1();
}
}
MyData.spec.js
describe('MyData', () => {
it('should execute method 4', function() {
let foo = new MyData(true);
foo.underProcessing.then(()=>{
// How do I verify that method4 was executed ??
expect(foo.method4.callCount).to.equal(1);
});
});
})
Here's an example:
const expect = require('chai').expect;
const sinon = require('sinon');
const sinonTest = require('sinon-test');
sinon.test = sinonTest.configureTest(sinon);
sinon.testCase = sinonTest.configureTestCase(sinon);
describe("MyData", () => {
it("should execute method 4", sinon.test(function() {
let spy = this.spy(MyData.prototype, 'method4');
let foo = new MyData(true);
return foo.underProcessing.then(() => {
expect(spy.callCount).to.equal(1);
});
}));
});
As an additional requirement, I added sinon-test because it's really useful to help clean up spies/stubs after the test has run.
The main feature is this line:
let spy = this.spy(MyData.prototype, 'method4');
This replaces MyData.prototype.method4 by a Sinon spy, which is a pass-through function (so it calls the original) that will record how exactly it was called, how often, with what arguments, etc. You need to do this before the instance is created, because otherwise you're too late (the method might already have been called through the chain of method calls that starts with this.init() in the constructor).
If you want to use a stub instead, which is not pass-through (so it won't call the original method), you can do that as well:
let spy = this.stub(MyData.prototype, 'method4').returns(Promise.resolve('yay'));
So instead of calling thirdPartyAPI.getData() and returning its result, method4 will now return a promise resolved with the value yay.
The remaining code should speak for itself, with one caveat: an explicit return in front of foo.underProcessing.then(...).
I assume that foo.underProcessing is a promise, so it's asynchronous, which means that your test should be asynchronous as well. Since Mocha supports promises, when you return a promise from a test, Mocha will know how to deal with it properly (there's an alternative method of making an asynchronous test with Mocha, involving callback functions, but when you're testing promise-based code you shouldn't really use those since it's easy to run into timeouts or swallowed exceptions).

Passing a lambda with return value into a callback without return value

This question involves boost::asio but is a pure C++ 11 question.
I am new to C++ 11 & lambda techniques which I am trying to use with boost::asio::async_connect for network communication.
Following is my function which attempts an asynchronous connect with the host.
bool MyAsyncConnectFunction() {
//some logic here to check validity of host
if (ip_is_not_resolved)
return false;
the_socket.reset(new tcp::socket(the_io_service));
auto my_connection_handler = [this]
(const boost::system::error_code& errc, const tcp::resolver::iterator& itr)
{
if (errc) {
//Set some variables to false as we are not connected
return false;
}
//Do some stuff as we are successfully connected at this point
return true;
};
//How is async_connect taking a lambda which
boost::asio::async_connect(the_socket, IP_destination, tcp::resolver::iterator(), my_connection_handler);
return true;
}
All works fine. There are no functional issues absolutely. However, I am wondering that boost::asio::async_connect takes a ConnectionHandler without a return type in its last parameter but I am passing a lambda i.e. my_connection_handler which returns a value.
How is it possible that I can pass a lambda with a return value whereas boost::asio::async_connect's 4th param takes a callback without a return value ?
boost::asio::async_connect is a function template that takes a callable as its fourth argument. It does not use the return value of said callable, nor does it care about it. Just as you could write :
auto f = []() { return true; };
f(); // Return value is discarded
The example of #m.s. is good too. Since it is a template, the function resolves the argument according to the template argument deduction rules.

Resources