Использование Aurelia Fetch прервано после обновления NPM
Я только недавно сделал npm update
в моем проекте Aurelia CLI с использованием TypeScript в Visual Studio 2015. Я использую aurelia-fetch-client
для звонков в мой бэкэнд Web API (.NET Core).
Это пример кода, который ранее компилировался и работал нормально:
import { autoinject } from "aurelia-framework";
import { HttpClient, json } from "aurelia-fetch-client";
import { SupportedCultureInfo } from "../../model/Resources/SupportedCultureInfo";
@autoinject()
export class ResourceService {
constructor(private http: HttpClient) {
}
getSupportedCultures(): Promise<SupportedCultureInfo[]> {
return this.http.fetch("resource/cultures").then(response => response.json());
}
}
Ни Visual Studio, ни ReSharper не предоставляют никаких указаний в пользовательском интерфейсе редактора кода, что это не скомпилируется, однако после недавнего обновления моя сборка теперь не работает с этой ошибкой:
TS2322: Type 'Promise<Response>' is not assignable to type 'Promise<SupportedCultureInfo[]>'
Единственный обходной путь, который я нашел, - это вернуться Promise<any>
вместо. Здесь я действительно хочу сделать возвращаемые классы, сопоставленные с результатом JSON, и иметь возвращаемый тип метода, который также должен быть строго типизированным Promise.
Кто-нибудь знает, что изменилось в последнее время, что может вызвать это? Это очень расстраивает.
ОБНОВИТЬ:
Это код, который я смог получить работать:
import { autoinject } from "aurelia-framework";
import { HttpClient, json } from "aurelia-fetch-client";
import { SupportedCultureInfo } from "../../model/resources/SupportedCultureInfo";
@autoinject()
export class ResourceService {
constructor(private http: HttpClient) {
}
getSupportedCultures(): Promise<SupportedCultureInfo[]> {
return this.http.fetch("resource/cultures")
.then(response => response.json())
.then<SupportedCultureInfo[]>((data: any) => {
const result = new Array<SupportedCultureInfo>();
for (let i of data) {
const info = new SupportedCultureInfo();
info.cultureCode = i.cultureCode;
info.name = i.name;
info.isCurrentCulture = i.isCurrentCulture;
result.push(info);
}
return result;
});
}
}
Мне пришлось сделать две вещи, которые не были очевидны сразу:
- Используйте обобщенную перегрузку then(), чтобы указать тип возвращаемого значения, которое я хочу использовать
- Явно объявить
any
введите для параметра JSON во втором обратном вызове, в противном случае транспортер gulp считает, что он по-прежнему типизирован как Response.
1 ответ
ОБНОВИТЬ:
Я случайно нажал Enter, в результате чего комментарий был оставлен незаконченным. Я не могу редактировать комментарий, поэтому обновляю свой ответ согласно обновленному вопросу.
Цепные обратные вызовы: если API resource/cultures
возвращает ответ как SupportedCultureInfo[]
а также getSupportedCultures()
просто нужно вернуть ответ таким, какой он есть, тогда второй обратный вызов не требуется. Ответ, который я разместил ранее, будет достаточным.
Я предполагаю, что второй обратный вызов, скорее всего, требуется в любом из этих двух случаев (или по какой-то другой причине)
- API возвращает другой тип, который должен быть сопоставлен
SupportedCultureInfo[]
- Ответ API требует дальнейшей обработки перед отправкой
getSupportedCultures()
Если вам требуется второй обратный вызов для дальнейшей обработки ответа, вам следует вызвать общий then<TResult>
метод, пока вы читаете ответ как json
вместо того, чтобы в более поздней части в цепи обратного вызова.
Причина сообщения об ошибке: в обновленном коде причину обрабатывает gulp транспилер data
как тип Response
связано с тем, что не является общим then(response => response.json())
используется который возвращает Promise<Response>
,
Вместо этого используйте then<SupportedCultureInfo[]>(response => response.json())
который бы вернулся Promise<SupportedCultureInfo[]>
или же then<any>(response => response.json())
который бы вернулся Promise<any>
,
Используя либо then<SupportedCultureInfo[]>(response => response.json())
или же then<any>(response => response.json())
даст вам data
во втором обратном вызове как SupportedCultureInfo[]
или же any
соответственно.
getSupportedCultures(): Promise<SupportedCultureInfo[]> {
return this.http.fetch("resource/cultures")
.then<SupportedCultureInfo[]>(response => response.json())
.then(data => {
// data will be of type SupportedCultureInfo[]
});
}
В качестве сигнатуры метода для then<TResult>
не поврежден, должен давать строго типизированный data
Название переменной.
Решение
Изменения в typescript
подразумевает, что мы указываем return
введите в качестве параметра типа then<TResult>
обратный вызов, как показано ниже.
getSupportedCultures(): Promise<SupportedCultureInfo[]> {
return this.http.fetch("resource/cultures").then<SupportedCultureInfo[]>(response => response.json());
}
Подробности:
Я столкнулся с той же ситуацией, когда я сделал npm update
, Хотя мои первоначальные мысли были виноваты aurelia-fetch-client
Я также покопался в исходном коде, чтобы внести исправление в эту проблему. Но в моем поиске я обнаружил, что typescript
настоящий преступник здесь.
interface Promise<T>
были некоторые изменения в способе, тогда callback обрабатывает возвращаемые типы. Теперь желаемый return
тип должен быть передан как параметр типа TResult
в then<TResult>
Перезвоните.