how to access a function in a promise - es6-promise

my code in react application
I have I class:
class SampleModuleController{
getSampleModuleSheet()
{
console.log("getSampleModuleSheet");
return tableSheet;
}
retrivePageData(pageNumber,pageLength){
console.log("retrivePageData calledd");
let pageData= asyncAwaitService.findTablePageTestData(pageNumber,pageLength);
return pageData;
}
}
export let sampleModuleController = new SampleModuleController();
SampleModuleController class lazy loaded and its getSampleModuleSheet method can use successfully.
in jsx:
<DataTable getPageData={import('../controllers/sampleModuleContrller').then(({sampleModuleController}) => {return sampleModuleController.retrivePageData;})} />
in js file:
async newPageManager(){
console.debug("this.props.getPageData------",this.props.getPageData);
let pageData = await props.getPageData(1,34);
}
out put
so how can I call the fuction inside the promise

in your jsx, it's apparent that the promise returns a method delegate.
So, this.props.getPageData when resolved with await will result in a method delegate that is itself to be invoked on.
we'll modify your snippet as followed;
async newPageManager(){
console.debug("this.props.getPageData------",this.props.getPageData);
let getPageData = await props.getPageData;
let pageData = getPageData(1,34);
}
additionally, since props.getPageData is returning a promise, it is thenable.
so, you could pass the result of that promise into a then function scope -- something like the following
async newPageManager(){
console.debug("this.props.getPageData------",this.props.getPageData);
let getFirstPagePromise = props.getPageData.then((fn) => fn.bind(this, 1, 32));
let getFirstPage = await getFirstPagePromise;
let pageData = getFirstPage();
}

Related

Use data accross all components

Created a component where I call all my api's. How do I use that data across all my other components
export let resultData = axios
.get(`https://swapi.dev/api/people/1`) //used a dummy api to test
.then(({ data }) => data);
export default class CacheService {
static myInstance = null;
result = resultData;
static getInstance() {
if (CacheService.myInstance == null) {
CacheService.myInstance = new CacheService();
}
return this.myInstance;
}
findAll() {
console.log(this.result);
return this.result;
}
}
You have created a promise and assigned to resultData variable but its not actually resolved.
Either you can use await or use then to get the data.
let testData = await newData.findAll();
or
newData.findAll().then((data)=>{
testData = data;
});
You need to await for the axios to resolve.
async findAll() {
const actualResult = await this.result;
console.log(actualResult);
return actualResult;
}

Access the common method from other component

Here I am using some method for frequently used methods in common method ts file. If I am going to access these method I got null values Please help me out.
CommonMethod.ts:
GetCategoryList(){
let Mylist = [];
this.auth.Get("Master/Category").then((user) => {
Mylist= user.json();
});
return Mylist;
}
My Another component:
I am trying to access common method ts file here. by below way.
import {CommonMethod} from './CommonMethod';
...
...
construtor(private com:CommonMethod){}
ngOninit(){
console.log(this.com.GetCategoryList());
}
this.auth.Get is going to be async in nature due to which the return MyList line will get called even before the callback to the then method is called and the data is arrived and set in MyList.
You can use the async await syntax to fix it:
async GetCategoryList() {
let Mylist = [];
const user = await this.auth.Get("Master/Category");
Mylist = user.json();
return Mylist;
}
You can then use it like this in your Component:
import {CommonMethod} from './CommonMethod';
...
...
construtor(private com: CommonMethod) {}
async ngOninit() {
const myList = await this.com.GetCategoryList();
console.log(myList);
}
PS: Make sure that CommonMethod is a service and is added to the providers array of your #NgModule
Should update your common method:
GetCategoryList(): Promise<any>{
let Mylist = [];
return this.auth.Get("Master/Category").then((user) => {
Mylist= user.json();
Promise.resolve(Mylist);
});
}
And
ngOninit(){
this.com.GetCategoryList().then(results=>{
console.log(results);
});
}

unable to mock HttpClient in Jasmine and Karma using HttpTestController

I am testing AuthService which sends user login info to server using another HelperService.
public authServiceSigninUser(user:UserSigninInfo):any{
console.log('In authServiceSigninUser. contacting server at '+this.API_URL +this.SIGNIN_USER_URL +" with user data "+user+ " with httpOptions "+httpOptions.withCredentials + ","+httpOptions.headers ); //TODOM password should be sent in encrypted format.
let signinInfo= new UserSigninAPI(user);
let body = JSON.stringify(signinInfo);
return this.helperService.sendMessage(this.SIGNIN_USER_URL,body,httpOptions)
}
I am trying to test the authServiceSigninUser method as follows but when I run the spec, I get error TypeError: Cannot read property 'subscribe' of undefined. It seems that the Observable.Why? The test spec is
describe('authServiceSigninUser test suite',()=>{
beforeEach(()=>{
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [AuthService, HelperService]
});
});
fit('should sign in user',()=>{
let spy:any;
let helper = TestBed.get(HelperService);
console.log("helper services is ",helper);
let authService = TestBed.get(AuthService);
console.log("auth services is ",authService);
let userSignIn = new UserSigninInfo("test#test.com","test");
let httpMock = TestBed.get(HttpTestingController);
spyOn(helper,'sendMessage');
const responseData = { result: 'success', ['additional-info']: 'login success' };
let httpEvent:HttpResponse<any> = new HttpResponse<any>({body:responseData});
let observable:Observable<HttpEvent<any>> = authService.authServiceSigninUser(userSignIn);
console.log("observable ",observable);//this is undefined
let subscription = observable.subscribe((event)=>{ //error here
console.log('event from authService',event);
});
const mockReq:TestRequest = httpMock.expectOne(environment.apiUrl+environment.signinUserUrl); //Expect that a single request has been made which matches the given URL, and return its mock
//once mocking of sending request is done, mock receiving a response. This will trigger the logic inside subscribe function
mockReq.flush(httpEvent); //flush method provides dummy values as response
httpMock.verify();//verify checks that there are no outstanding requests;
expect(helper.sendMessage).toHaveBeenCalled();
});
});
sendMessage in HelperService is
sendMessage(url:string, body:any,httpOptions):Observable<HttpEvent<any>> {
this.loaderService.show();
let observable:Observable<HttpEvent<any>> = this.http.post<any>(url,body,httpOptions);
return observable.pipe(
tap((httpEvent:HttpEvent<any>) => {//tap transparently perform actions or side-effects, such as logging.
if(httpEvent.type === HttpEventType.Response)
{
console.log('response from backend service:', httpEvent);
}
else {
console.log("not an http response")
}
return httpEvent;
})
,catchError(err=>this.handleError(err))
,finalize(()=> this.loaderService.hide()));
}
I don't know why the above test doesn't work but I think that my approach in general about testing isn't correct. As I am unit testing AuthService, I probably should mock the responses I expect from methods of dependent services. Eg, I should spyOn sendMessage and return a mock value. Also my object should be to test that sendMessage was called with correct arguments.
describe('authServiceSigninUser test suite',()=>{
beforeEach(()=>{
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],//need this as HelperSerice needs HttpClient and this module provides it. I could have also used HttpClientModule
providers: [AuthService, HelperService]
});
});
fit('should send request to sign in user',()=>{
// let spy:any;
let helper = TestBed.get(HelperService);
//console.log("helper services is ",helper);
let authService = TestBed.get(AuthService);
//console.log("auth services is ",authService);
let userSignIn = new UserSigninInfo("test#test.com","test"); //data to send to server
//response expected from sendMessage
const responseData = { result: 'success', ['additional-info']: 'login success' };
let httpEvent:HttpResponse<any> = new HttpResponse<any>({body:responseData});
spyOn(helper,'sendMessage').and.returnValue(new Observable(()=>{
httpEvent
})); //when sendMessage is called, return the mocked response
let observable:Observable<HttpEvent<any>> = authService.authServiceSigninUser(userSignIn); //now when authServiceSignInUserr is called, it will call sendMessage and the spyOn will return mocked response
console.log("observable returned ",observable);
let subscription = observable.subscribe((event)=>{
console.log('event from authService',event);
});
//check that the arguments passed to sendMessage are correct
let APIToBeUsed = authService.SIGNIN_USER_URL;
let JSONToBeUsed = JSON.stringify(new UserSigninAPI(userSignIn));
let HTTPOptionsToBeUsed = authService.httpOptions;
expect(helper.sendMessage).toHaveBeenCalledWith(APIToBeUsed,jasmine.any(String),jasmine.any(Object));
expect(helper.sendMessage).toHaveBeenCalledWith(jasmine.any(String),JSONToBeUsed,jasmine.any(Object));
expect(helper.sendMessage).toHaveBeenCalledWith(jasmine.any(String),jasmine.any(String),HTTPOptionsToBeUsed);
});
});

Ava unbinds this for t.throws

AVA seems to unbind the instance methods 'this'.
class Person {
constructor(name) {
this.name = name;
}
sayMyName() {
const name = this.name;
return new Promise(function (resolve, reject) {
reject(new Error(name));
});
}
}
test('test', async (t) => {
const person1 = new Person('Bob');
const error = await t.throws(person1.sayMyName);
t.is(error.message, 'Bob');
});
For the above code, I get this:
85: const error = await t.throws(person1.sayMyName);
86: t.is(error.message, 'Bob');
87: });
Difference:
"CannBot read property \'name\' of undefinedb"
I've tried manually binding this promise like this:
person1.sayMyName.bind(person1), but this doesn't seem to work either.
t.throws() accepts a promise, so you just need to call your function:
const error = await t.throws(person1.sayMyName());
Bonus tip:
If you only need to check the error message, your assertion could be simplified to the following:
await t.throws(person1.sayMyName, 'Bob');
AVA seems to unbind the instance methods 'this'.
No, that's how this works in JavaScript. If you pass a class method, you need to bind it to its instance to preserve this. You might find my auto-bind module handy for this.

await doesn't seem to wait till the async call is finished

I have the async function which uses await calls and I thought that when you use await, it should pause the function execution until the value it received. For some reason, it doesn't work with me.
Here's my function (it is inside a class):
async userExistsInDB(email) {
let userExists;
await MongoClient.connect('mongodb://127.0.0.1:27017/notificator', async(err, db) => {
if (err) throw err;
let collection = db.collection('users');
userExists = await collection.find({email: email}).limit(1).count() > 0;
console.log("INSIDE:\n", userExists);
db.close();
});
console.log("OUTSIDE:\n", userExists);
return userExists;
}
And here's how I call it in another function inside the same class:
async getValidationErrors(formData) {
let userExists = await this.userExistsInDB(formData.email);
console.log("ANOTHER FUNC:\n", userExists);
}
So, I get the following output:
OUTSIDE:
undefined
ANOTHER FUNC:
undefined
INSIDE:
true
although the value INSIDE: true I expect to get printed the first.
Basically, what I need is to get the boolean value userExists from the userExistsInDB function and use it in other code.
What am I doing wrong here?
await only works with promises, so MongoClient.connect(…) would need to return a promise. Yet, you are using it as a callback API, and even with an async (promise-returning) callback function, which is not gonna work. Assuming mongo returns promises if you don't pass a callback, your code should look like
async function userExistsInDB(email) {
let db = await MongoClient.connect('mongodb://127.0.0.1:27017/notificator');
let collection = db.collection('users');
let userExists = (await collection.find({email: email}).limit(1).count()) > 0;
db.close();
return userExists;
}
though ideally you'd rather do
async function userExistsInDB(email) {
let db = await MongoClient.connect('mongodb://127.0.0.1:27017/notificator');
try {
let collection = db.collection('users');
let userCount = (await collection.find({email: email}).limit(1).count();
return userCount > 0;
} finally {
db.close();
}
}