Bim*_*P.B 1 javascript aurelia
我有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;
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我试图从服务器和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;
}
}Run Code Online (Sandbox Code Playgroud)
在这段代码中,我正在调用函数GetInstallationId(),api_services.ts但它并没有等待http request完成.有没有办法在执行后使下一个语句中的语句执行GetInstallationId()?
简短的回答:您需要支持异步行为.
你可以通过(a)Promises和/或(b)async/await来做到这一点.除了IE 11之外,所有浏览器都支持前者,如果你需要支持IE 11,那么有像这样的polyfill.后者目前在IE中根本不受支持,因为它需要新的JS关键字/语法必须与一个转换器一起使用像巴贝尔.
这个答案将使用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);
});
}
}
Run Code Online (Sandbox Code Playgroud)因为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));
}
...
Run Code Online (Sandbox Code Playgroud)
}
上面的函数只是一个跨浏览器工作的例子.另一个需要ES6支持和/或转换的解决方案是使用箭头功能:
//
// 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);
});
}
...
}
Run Code Online (Sandbox Code Playgroud) 通过上面的重构,您现在可以getInstallationID()从例如另一个视图模型调用:
import {AppServices} from '...';
import {autoinject} from 'aurelia-framework';
@autoinject()
export class SomeViewModel {
constructor(appServices) {
this.appServices = appServices;
}
callGetInstallationId() {
this.appServices.getInstallationID().then(function(id) {
// the ID that is passed here is the one that is `accept`ed.
// ie. if AppServices.getInstallationID calls accept('123'), then
// the '123' will be passed to this function as the first argument
}, function(e) {
// this function will be called if AppServices.getInstallationID
// calls reject. e will be the Error object, if any, that is passed
// to the reject method.
});
}
}
Run Code Online (Sandbox Code Playgroud)