angular - Hur man implementerar löften i Ionic/Cordova
Jag bygger en Ionic-app som fungerar med tokenbaserad autentisering. När användaren autentiserar sparas en åtkomsttoken i lokal lagring.
Min kod anropar sedan en leverantör för vilka data den än behöver (i det här fallet hämtar den 'Träningsprogram' från ett API).
I sin tur anropar den leverantören en annan leverantör som hanterar HTTP-förfrågningar för mitt API. Den ställer effektivt in de nödvändiga rubrikerna och initierar HTTP-förfrågan, och returnerar sedan svaret tillbaka till den begärande leverantören.
Allt detta fungerar bra, tills jag behöver hämta åtkomsttoken från lagringen innan jag gör HTTP-förfrågan. Det verkar som att åtkomst till data från lagringen inte är omedelbar, utan istället använder then-syntaxen.
Det verkar som att när jag anropar leverantören från min kod så går anropet vidare till leverantören av träningsprogram, och sedan vidare till API-leverantören. Koden här körs sedan och skickas tillbaka upp, men detta händer innan min app har möjlighet att hämta det jag behöver från lagring.
Jag försökte placera allt i förfrågan inne i then-anropet av storage.get-metoden, men det fungerade inte.
Här är min begärande kod:
this.trainingProgramme.get_programmes().subscribe((res) => {
loader.dismiss();
console.log(res);
});
Vilket filtreras ner till min trainingProgramme-leverantör:
get_programmes() {
let seq = this.api.get('training-programmes');
seq
.map(res => res.json())
.subscribe();
return seq;
}
Vilket i sin tur går vidare till min api-leverantör:
export class Api {
base_url: string = 'https://******.com';
url: string = this.base_url + '/api/v1';
access_token: string;
constructor(
public http: Http,
private storage: Storage) {
// Grab access token and store it
storage.get('access_token').then((val) => {
console.log('Pulled access token from local storage', val);
this.access_token = val;
});
}
// Performs a GET request with auth headers
get(endpoint: string, params?: any) {
let headers = new Headers();
headers.append('Authorization', 'Bearer ' + this.access_token);
let options = new RequestOptions({ headers: headers });
return this.http.get(this.url + '/' + endpoint, options);
}
}
Detta ger inga fel, men de headers som skickas är:
Authorization: Bearer undefined
Sammanfattningsvis: Jag tror att storage-anropet sker asynkront, så HTTP-anropet initieras innan det har möjlighet att hämta åtkomsttoken. Hur kan jag förhindra att detta händer eller vänta på att storage ska slutföras innan jag gör HTTP-anropet? Att bara placera min kod inuti then fungerar inte, eftersom denna metod redan är inom subscribe, så jag får fel.
UPPDATERING 1:
Nedan är koden jag har använt där jag placerade storage-koden inne i metoden själv, istället för i konstruktorn, och sedan placerade all kod, inklusive HTTP-anropet, inne i then.
// Performs a GET request with auth headers
get(endpoint: string, params?: any) {
// Grab access token and store it
this.storage.get('access_token').then((val) => {
console.log('Pulled access token from local storage', val);
this.access_token = val;
let headers = new Headers();
headers.append('Authorization', 'Bearer ' + this.access_token);
let options = new RequestOptions({ headers: headers });
return this.http.get(this.url + '/' + endpoint, options);
});
}
Felen med:
Runtime Error
Uncaught (in promise):
TypeError: Cannot read property 'map' of undefined
TypeError: Cannot read property 'map' of undefined at TrainingProgramme.get_programmes
Förmodligen beror detta på att get-metoden inte returnerar något när det förväntas, eftersom returvärdet nu är asynkront.
Svar #1
prova detta :)
yourlongmethod() {
return new Promise((resolve, reject) => {
//your code
var data = "Any data you want to return with the promise";
resolve(data);
});
}
Då kan du kalla detta
yourlongmethod().then((res) => {
console.log(res) })
Svar #2
I din api-leverantörs konstruktor skriver du din kod för att hämta de lagrade uppgifterna, vilket är asynkront. Kom ihåg att JavaScript är synkront, så när det asynkrona har anropats, menar jag store.get().then(), så är konstruktor-delen slutförd. Den väntar inte på att värdet ska lagras i this.access_token och den anropar get()-funktionen.
För att få storage.get asynkrona anrop att vänta tills det är klart och sedan gå vidare och anropa get()-metoden, använd helt enkelt nyckelorden async och await
constructor(
public http: Http,
private storage: Storage) {
this.getAccessToken(); //only after completing this function it will go the next command
}
async getAccessToken(){
// Grab access token and store it
//below i have writen await inorder to wait until this is completed.
const token = await storage.get('access_token').then((val) => {
console.log('Pulled access token from local storage', val);
this.access_token = val;
});
}
försök att placera ovanstående kod och kontrollera, hoppas det hjälper dig
