我很难弄清楚为什么我的等待语句没有得到尊重,代码在完成异步函数之前就开始了。
我的代码:
async getSensors(boardId: number): Promise<Sensor[]> {
console.log('call sensor');
const sensors: Sensor[] = [];
await this.http.get<object[]>(API_URL + 'sensors/' + boardId).toPromise().then(res => {
console.log('http sensor');
res.forEach(r => sensors.push(GenericDeserialize(r, Sensor)));
});
console.log('return sensor');
return sensors;
}
async getRelays(boardId: number): Promise<Relay[]> {
console.log('call relay');
const relays: Relay[] = [];
await this.http.get<object[]>(API_URL + 'relays/' + boardId).toPromise().then(res => {
console.log('http relay');
res.forEach(r => relays.push(GenericDeserialize(r, Relay)));
});
console.log('return relay');
return relays;
}
async getBoards(): Promise<Board[]> {
const boards: Board[] = [];
await this.http.get<object[]>(API_URL + 'boards').toPromise().then(async res => {
console.log('http boards');
await res.forEach(async b => {
console.log('loop', b);
const board = GenericDeserialize(b, Board);
await this.getSensors(board.boardId).then(sensors => board.sensors = sensors);
await this.getRelays(board.boardId).then(relays => board.relays = relays);
boards.push(board);
});
});
console.log('return boards');
return boards;
}我的茉莉花测试:
it('should have two sensors and one relay', async () => {
const service: DataService = TestBed.get(DataService);
const boards = await service.getBoards();
const board = boards[0];
expect(board.sensors.length).toBe(2);
expect(board.relays.length).toBe(1);
});这是控制台在运行测试时输出的实际“调用堆栈”:
'return relay'
'http relay'
'return relay'
'http boards'
'loop', Object{board_id: 0, board_name: 'test'}
'call sensor'
'loop', Object{board_id: 1234, board_name: 'esp1'}
'call sensor'
'return boards'这就是我所期待的“呼叫堆栈”:
'http boards'
'loop', Object{board_id: 0, board_name: 'test'}
'call sensor'
'http sensor'
'return sensor'
'call relay'
'http relay'
'return relay'
'loop', Object{board_id: 1234, board_name: 'esp1'}
'call sensor'
'http sensor'
'return sensor'
'call relay'
'http relay'
'return relay'
'return boards'发布于 2019-06-28 13:41:28
你的问题是:
await res.forEach(async b => {
console.log('loop', b);
const board = GenericDeserialize(b, Board);
await this.getSensors(board.boardId).then(sensors => board.sensors = sensors);
await this.getRelays(board.boardId).then(relays => board.relays = relays);
boards.push(board);
});forEach总是返回undefined,而await undefined只等待一个微滴答;而forEach完全忽略了回调的返回值,因此回调创建的承诺永远不会用于任何事情,也不会等待它们。
如果要在并行中处理这些数据,只需将其改为map并添加Promise.all即可。
await Promise.all(res.map(async b => {
console.log('loop', b);
const board = GenericDeserialize(b, Board);
await this.getSensors(board.boardId).then(sensors => board.sensors = sensors);
await this.getRelays(board.boardId).then(relays => board.relays = relays);
boards.push(board);
}));如果要在系列中执行这些操作,请使用循环:
for (const b of res) {
console.log('loop', b);
const board = GenericDeserialize(b, Board);
await this.getSensors(board.boardId).then(sensors => board.sensors = sensors);
await this.getRelays(board.boardId).then(relays => board.relays = relays);
boards.push(board);
}附带注意:你做了很多this.http.get<object[]>(API_URL + /*...*/).toPromise()。我倾向于用一种实用的方法:
callAPI(call: string): Promise<object[]> {
return this.http.get<object[]>(API_URL + call).toPromise();
}这也使得这样的改变是合理的:
await this.http.get<object[]>(API_URL + 'relays/' + boardId).toPromise().then(res => {
console.log('http relay');
res.forEach(r => relays.push(GenericDeserialize(r, Relay)));
});至
relays.push(...(await this.callAPI('relays/' + boardId)).map(r => GenericDeserialize(r, Relay)));或者如果你真的想要那个console.log
relays.push(...(await this.callAPI('relays/' + boardId)).map(r => {
console.log('http relay');
return GenericDeserialize(r, Relay);
}));https://stackoverflow.com/questions/56807968
复制相似问题