I'm unable to get the data response from unsplashAxios within the GetPhoto constructor, at the moment it just says 'Promise { }'. Have I missed something blatantly obvious or does this need rethinking?
Attempt 1
class Unsplash {
constructor(path) {
return new Promise((resolve, reject) => {
unsplashAxios(path)
.then(response => {
resolve(response);
})
.catch(error => {
reject(error);
});
});
}
}
class GetPhoto {
constructor() {
console.log('Get Photo');
const unsplash = new Unsplash('/photos/PgHc0Ka1E0A');
console.log(unsplash)
// Console.log Response - Promise { <pending> }
}
}
Attempt 2
class Unsplash {
constructor(path) {
return unsplashAxios(path)
}
}
class GetPhoto {
constructor() {
const unsplash = new Unsplash('/photos/PgHc0Ka1E0A');
unsplash.then((response) => {
console.log(response)
}).catch((response) => {
console.log(response);
});
}
}
Attempt 3 - After #Klaycon I've rewrote the above and this seems to work. But feedback would be great (good or bad).
const unsplashAxios = require('./unsplashAxios');
// Class
class Unsplash {
// Constructor
constructor() {
this.unsplash = null;
}
// Method
getPhoto(id){
this.unsplash = unsplashAxios( `/photos/${id}`);
this.unsplash.then((response) => {
console.log(response)
}).catch((response) => {
console.log(response);
});
}
// Method
getCollection(id){
this.unsplash = unsplashAxios(`/collections/${id}/photos`);
this.unsplash.then((response) => {
console.log(response)
}).catch((response) => {
console.log(response);
});
}
}
// Instance
myUnsplash = new Unsplash();
// Method
myUnsplash.getPhoto('PgHc0Ka1E0A');
// Method
myUnsplash.getCollection('62890');
You return a Promise.
As #Bergi said in your comment, avoid to use them in a constructor.
Use :
unsplash.then((data) => {
//do something with data
});
to wait til the promise is resolved. You can read more about promises here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Since unsplashAxios is already returning a promise, you don't need to wrap it in another promise (you're resolving unsplashAxios's promise then putting that result into another Promise that would have to be resolved elsewhere. Changing your code to this should work:
constructor(path) {
unsplashAxios(path)
.then(response => {
//do something with the response
})
.catch(error => {
//do something with the error
}
}
}
I ended up rewriting and found the following to work as expected:
class Unsplash {
constructor(path) {
return unsplashAxios(path)
}
}
class GetPhoto {
constructor() {
const unsplash = new Unsplash('/photos/PgHc0Ka1E0A');
unsplash.then((response) => {
console.log(response)
}).catch((response) => {
console.log(response);
});
}
}
Related
This code should do the following:
Search all links on the current page and check for multiple errors.
The check should be before showing up the results on the page.
So I want to fill an array with errors and return it after all checks are finished.
interface LinkObject {
element: HTMLAnchorElement;
url: URL;
checkTrigger?: HTMLButtonElement;
}
interface ErrorObject {
element: HTMLElement;
errors: string[];
warnings: string[];
}
export default class LinkCheckTool {
protected linksObjects: LinkObject[] = [];
protected errors: ErrorObject[] = [];
constructor() {
document.querySelectorAll('a').forEach((linkElement) => {
const button: HTMLButtonElement = document.createElement('button');
button.classList.add('tb-o-linkobject__btn');
const url: URL = new URL(linkElement.href);
if (url) {
linkElement.appendChild(button);
this.linksObjects.push({
element: linkElement,
url: url,
checkTrigger: button
})
}
})
const errors = this.fetchErrors();
console.log(errors); // results in an empty array, so need to use async / await here
}
protected fetchErrors() {
const errors = [];
this.linksObjects.forEach((linkObject) => {
if (linkObject.url.protocol !== 'javascript:') {
fetch(linkObject.url.href)
.then((response) => (response))
.then((response) => {
if (!response.ok) {
// push to errors here
}
})
.catch((error) => {
// push to errors here
})
}
})
}
}
In this case, the console output of errors returns an empty array, of course. How can I use async / await and return a promise here?
Function fetchErrors is not async here, because it does not return Promise. And since you try to call the function in the constructor async/await syntax won't really work in this context.
What you need to do instead is to use Promise callback here. You can apply the Promise.allSettled method. It will help you to wait until your requests will get resolved and then you can handle the responses one by one.
constructor() {
// ...
const errors = [];
this.fetchErrors().then(results => {
results.forEach(result => {
if (result.status === "rejected") {
errors.push(result.value)
}
})
console.log(errors); // will print you list of errors
});
}
protected fetchErrors() {
const requests = this.linksObjects
.filter(linkObject => linkObject.url.protocol !== 'javascript:')
.map((linkObject) => fetch(linkObject.url.href))
return Promise.allSettled(requests);
}
I am trying to perform a GET call in typescript to various services and capture a value from their json response which will be passed in as a param in another function.
Through some online searching, I bumped into axios but am having a hard time wrapping my head around asynchronous apis and how to handle promises. Here is the code, that returns 'undefined' as an output.
function getVersion(url: string) {
let version;
let res = await axios.get(url)
.then((response: { data: { buildInfo: { details: { version: any; }; }; }; }) => {
version = response.data.buildInfo.details.version;
return version;
})
.catch((error: any) => {
console.log(error);
});
return version;
}
I've also tried async/await but have trouble with unhandled promises. I don't need to use axios, any library will do as long as I can access the response to use in consequent functions.
you can return a promise for getVersion()
async function getVersion(url: string) {
let res = await axios.get(url)
.then((response: { data: { buildInfo: { details: { version: any; }; }; }; }) => {
let version = response.data.buildInfo.details.version;
return new Promise((resolutionFunc) => { // return a promise
resolutionFunc(version);
});
})
.catch((error: any) => {
console.log(error);
});
return res;
}
getVersion(url).then(res => {console.log(res)}) // use
or you can just return the axios, beacuse axios will return a promise
async function getVersion(url: string) {
let res = await axios.get(url)
return res;
}
getVersion(url).then(res => {console.log(res)}) // use
import canUseDOM from '#utils/dist/env/canUseDOM';
declare global {
interface Window {
grecaptcha: any;
}
}
export default async function getRecaptchaTokenExplicit(params: { recaptchaClientId: number }) {
return new Promise(resolve => {
if (canUseDOM && window.grecaptcha) {
const { recaptchaClientId } = params;
window.grecaptcha.ready(() => {
window.grecaptcha
.execute(recaptchaClientId, {
action: 'submit',
})
.then(function(token: string) {
return resolve(token);
});
});
} else {
return resolve('');
}
});
}
Calling await above function, I used to get Timeout console error from recaptcha (found it was because of badge element get removed due to component rendering), but in order to avoid it, how do I capture it and resolve return empty string?
error looks like this:
Since the error is in the promise, have you tried to .catch() it?
window.grecaptcha
.execute(recaptchaClientId, {
action: 'submit',
})
.then(function(token: string) {
resolve(token);
})
.catch(err => {
console.error(err);
resolve('');
});
I'm using Google's reCaptcha V3 as part of my Angular(7) project.
I would like to wait for the Token's response before proceeding to the rest of the code and before checking whether the Token is validated or not.
declare var grecaptcha: any;
ngOnInit() {
this.validateCaptcha();
if(this.gToken)
{
...
}
}
gToken:string;
validateCaptcha()
{
let self = this;
grecaptcha.ready(function() {
grecaptcha.execute('reCAPTCHA_site_key', {action: 'homepage'}).then(function(token){
self.gToken = token;
});
});
}
The thing is that this.gToken is undefined because it doesn't wait to validateCaptcha to finish its job.
I have also tried async and await but it didn't help. perhaps I used it wrongly.
You can use Promise here.
You need to wait until token generated.
You can also use async / await instead of Promise.
ngOnInit() {
this.validateCaptcha().then(token => { // Here wait token generated
if(token) {
}
})
}
validateCaptcha() {
return new Promise((res, rej) => {
grecaptcha.ready(() => {
grecaptcha.execute('reCAPTCHA_site_key', {action:
'homepage'}).then((token) => {
return res(token);
})
})
})
}
Update example with async / await.
While using async / await the validateCaptcha method demonstrated above remains same (must return Promise)
async ngOnInit() { // async keyword added here
try {
let token = await this.validateCaptcha(); // await keyword added here
if(token) {
}
} catch(e) {
}
}
Why not have validateCaptcha() return a promise?
declare var grecaptcha: any;
ngOnInit() {
this.validateCaptcha().then(() => {
if(this.gToken)
{
...
}
});
}
gToken:string;
validateCaptcha()
{
let self = this;
return new Promise((resolve, reject) => {
grecaptcha.ready(function() {
grecaptcha.execute('reCAPTCHA_site_key', {action: 'homepage'}).then(function(token){
self.gToken = token;
resolve();
});
});
});
}
Under my Angular 6 app, I have a variable "permittedPefs" which is getting value after an HTTP call (asynchronous)
#Injectable()
export class FeaturesLoadPermissionsService {
permittedPefs = [];
constructor() {
this.loadUserPefsService.getUserRolePefs(roleId)
.subscribe(
(returnedListPefs) => {
this.permittedPefs = returnedListPefs;
},
error => {
console.log(error);
});
}
}
in another method, I'm using that same variable:permittedPefs
But as it's initially empty and it gots its value after such a time, so I need to wait for it to re-use it.
I've tried to use async-await, and my purpose is waiting for permittedPefs to got aobject value
async checkPefPresence(pefId) {
const listPefs = await this.permittedPefs
}
how to fix it ??
As loadUserPefsService.getUserRolePefs method returns Observable you can store it and subscribe to it later when you need it.
#Injectable()
export class FeaturesLoadPermissionsService {
permittedPefs = [];
constructor() {
this.userRolePefsObservable = this.loadUserPefsService.getUserRolePefs(roleId);
}
}
checkPefPresence(pefId) {
let listPefs;
this.userRolePefsObservable.subscribe(
(returnedListPefs) => {
listPefs = returnedListPefs;
},
error => {
console.log(error);
});
}
Use a behaviorSubject
#Injectable()
export class FeaturesLoadPermissionsService {
permittedPefs: BehaviorSubject<any[]> = new BehaviorSubject([]);
constructor() {
this.loadUserPefsService.getUserRolePefs(roleId)
.subscribe((returnedListPefs) => {
this.permittedPefs.next(returnedListPefs);
},
error => {
console.log(error);
});
}
}
Then where ever you are checking for it(remember to unsubscribe when you are done)
if it has to be async you can do it like below
async checkPefPresence(pefId): Promise {
return new Promise((resolve, reject) => {
this.featuresLoadPermissionsService.permittedPefs.subscribe(listPefs => {
//handle whatever check you want to do here
resolve();
},reject);
})