我有2个文件 1. api_service.ts
import { HttpClient } from 'aurelia-http-client';
import { autoinject } from "aurelia-framework";
import { ObserverLocator } from "aurelia-binding";
@autoinject()
export class ApiServices {
private app_url = 'http://example.com/';
private host = 'http://api.example.com:8080';
constructor(private store: Store, private client: HttpClient, private observerLocator: ObserverLocator) { }
GetInstallationId() {
let url = this.host + "/1/api/iid";
let iid;
this.client.get(url)
.catch((err) => { })
.then(res => {
let response = JSON.parse(res.response);
iid = response.iid;
});
return iid;
}
}
这里我试图从服务器和HTTP响应中获取一些价值,我可以看到我得到它。
import { Store } from './localstorage_service';
import { ApiServices } from './api_service';
import { autoinject } from "aurelia-framework";
import { ObserverLocator } from "aurelia-binding";
@autoinject()
export class AppServices {
private installation_ID: string;
constructor(private store: Store, private apiServices: ApiServices, private observerLocator: ObserverLocator) { }
getInstallationID() {
const iid = this.store.getValue('installation_ID');
console.log("iid = " + iid);
if (iid && iid != undefined) {
console.log('inside if iid');
// this.installation_ID = this.apiServices.GetInstallationId();
this.installation_ID = iid;
} else {
console.log('inside else iid');
this.installation_ID = this.apiServices.GetInstallationId();
}
this.store.setValue('installation_ID', this.installation_ID);
console.log("after if condition iid = " + iid);
return this.installation_ID;
}
}
此代码中我从GetInstallationId()
调用函数api_services.ts
,但它不等待http request
完成。有没有办法在执行GetInstallationId()
后执行下一个语句中的语句?
答案 0 :(得分:7)
简短的回答:您需要支持异步行为。
您可以通过(a)Promises和/或(b)async/await执行此操作。如果你需要支持IE 11,那么前者是supported in all browsers except IE 11并且有polyfills like this one。后者目前在IE中根本不受支持,因为它需要新的JS关键字/语法必须与转换器一起使用比如Babel。
这个答案将使用Promises,因为它们的依赖性比async / await少。下面的片段已更新为使用Promises - 查找以下评论:
// REPLACED THIS LINE
... // WITH THIS LINE
和
// ADDED THIS LINE
识别更新。
GetInstallationId
是一个异步函数,必须返回一个promise。
class ApiServices {
...
GetInstallationId() {
let url = this.host + "/1/api/iid";
return new Promise(function(accept, reject) {
let iid;
this.client.get(url)
.catch((err) => { })
.then(res => {
let response = JSON.parse(res.response);
// REPLACED THIS LINE
// iid = response.iid;
// WITH THIS LINE which accepts the promise
accept(response.iid);
})
// ADDED THIS LINE to catch any errors
// e.g. when invalid response received
.catch(reject);
});
}
}
由于getInstallationID
调用GetInstallationId
,因此它也必须返回一个承诺。此示例定义了一个单独的函数handler
,然后通过.bind(this)
进行绑定,以确保无论何时执行该函数,this
将始终返回正确的ApiService对象。
class AppServices {
...
getInstallationID() {
function handler(accept, reject) {
const iid = this.store.getValue('installation_ID');
console.log("iid = " + iid);
if (iid && iid != undefined) {
console.log('inside if iid');
// this.installation_ID = this.apiServices.GetInstallationId();
this.installation_ID = iid;
} else {
console.log('inside else iid');
// REPLACED THIS LINE
// this.installation_ID = this.apiServices.GetInstallationId();
// WITH THIS LINE
this.apiServices.GetInstallationId().then(accept,reject);
}
this.store.setValue('installation_ID', this.installation_ID);
console.log("after if condition iid = " + iid);
// REPLACED THIS LINE
// return this.installation_ID;
// WITH THIS LINE
accept(this.installation_ID);
};
return new Promise(handler.bind(this));
}
...
}
以上功能只是一个跨浏览器工作的例子。另一个需要ES6支持和/或转换的解决方案是使用箭头函数:
function handler(accept, reject) {
const iid = this.store.getValue('installation_ID');
console.log("iid = " + iid);
if (iid && iid != undefined) {
console.log('inside if iid');
// this.installation_ID = this.apiServices.GetInstallationId();
this.installation_ID = iid;
} else {
console.log('inside else iid');
// REPLACED THIS LINE
// this.installation_ID = this.apiServices.GetInstallationId();
// WITH THIS LINE
this.apiServices.GetInstallationId().then(accept,reject);
}
this.store.setValue('installation_ID', this.installation_ID);
console.log("after if condition iid = " + iid);
// REPLACED THIS LINE
// return this.installation_ID;
// WITH THIS LINE
accept(this.installation_ID);
};
return new Promise(handler.bind(this));
}
...
通过上述重构,您现在可以通过以下方式调用
//
// Arrow function version
//
class AppServices {
...
getInstallationID() {
// NOTE the => which is shorthand for `(function (accept,reject) {...}).bind(this)`
return new Promise((accept, reject) => {
const iid = this.store.getValue('installation_ID');
console.log("iid = " + iid);
if (iid && iid != undefined) {
console.log('inside if iid');
// this.installation_ID = this.apiServices.GetInstallationId();
this.installation_ID = iid;
} else {
console.log('inside else iid');
// REPLACED THIS LINE
// this.installation_ID = this.apiServices.GetInstallationId();
// WITH THIS LINE
this.apiServices.GetInstallationId().then(accept,reject);
}
this.store.setValue('installation_ID', this.installation_ID);
console.log("after if condition iid = " + iid);
// REPLACED THIS LINE
// return this.installation_ID;
// WITH THIS LINE
accept(this.installation_ID);
});
}
...
}
另一种视图模型如下:
getInstallationID()