跳转到主要内容

Angular引入信号已经有一段时间了,社区开始讨论这是前进还是后退。对我来说,这绝对是向前迈出的一步。

让我们快速回顾一下信号是什么,然后我们将快速介绍如何考虑您的公司应用程序以及如何重构它的步骤和技巧,讨论应该采取什么方法。

首先,在一开始,Angular团队采取了一种有点特殊的方法,并为所有事情引入了RxJs模式,即使在它不是最佳选择的用例中也是如此。例如,如果您想要发出HTTP请求、保存响应并在视图中显示它,则需要首先从Angular导入HttpClient,然后通过订阅它来调用API,或者使用.pipe()运算符创建另一个层。之后,您可以订阅它:

// API service
@Injectable()
export class FetchingApiService {
  constructor(private http: HttpClient) {}

  fetchTodos(): Observable<ToDoInterface[]> {
    return this.http.get<ToDoInterface[]>('https://jsonplaceholder.typicode.com/todos/');
  }
}

// facade service
@Injectable()
export class FetchingFacadeService {
  public allToDos$ = new BehaviorSubject(null);

  constructor(private fetchService: FetchingApiService) {}

  fetchTodos(): Observable<ToDoInterface[]> {
    return this.fetchService.fetchTodos().pipe(
      tap((todos: ToDoInterface[]) => {
        this.allToDos$.next(todos);
      })
    );
  }
}

// Component
  fetchTodos(): Observable<ToDoInterface[]> {
    return this.facade.fetchTodos();
  }

这种方法在很大程度上也依赖于Zone.js,它将重新渲染allToDos$,只是在向列表中添加新项目时渲染一次或几次。你可以在这个链接上查看我以前关于信号的文章:https://medium.com/@marekpanti/how-to-refactor-observable-patterns-to-angular-signals-3c998796e081

然而,对于信号,我们的方法会有所不同,我们将使用带有.fetch() api和async and await的javascript本地解决方案

// API Service
@Injectable()
export class FetchingApiService {
  async fetchTodosClassicApproach(): Promise<ToDoInterface[]> {
    const response = await fetch('https://jsonplaceholder.typicode.com/todos/');
    const todos = await response.json();
    return todos;
  }
}

// Facade

@Injectable()
export class FetchingFacadeService {
  public allTodosSignal = signal([]);

  constructor(private fetchService: FetchingApiService) {}

  async fetchTodos() {
    const myTodosResponse: ToDoInterface[] =
      await this.fetchService.fetchTodosClassicApproach();
    this.allTodosSignal.set(myTodosResponse);
  }

// Component .html
<div *ngFor="let todo of (facade.allTodosSignal())">

 

在这个解决方案中,我们保存了大量导入,同时,我们为下一个Angular版本准备了组件,当我们可以使用标志来指示组件正在使用信号,并且基本上不在Zone.js范围内时。

但是,当我们想更新应用程序以使用信号时,应该采取什么方法?

我建议创建三个票证:

1.重构所有component.ts,并使用.toSignal()方法将RxJs流更改为信号。有了这些,我们将有基于信号的观点,我们可以继续使用逻辑。

2.然后我将继续介绍服务和外观——在这里,您可以根据应用程序的层次和复杂性创建更多任务。所以我会把所有的.pipe()都改为计算信号。完成这一步骤后,基本上我们所有的应用程序都被重构了,但不要忘记最后一步。

const name = signal('John');
const lastName = signal('Doe');
// computed can use if and other function, so you don't need to chain your operators
const FullName = Signal<string> = computed(() => name + lastName);

3.更改所有使用httpClient for native解决方案的API调用。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

总之,如果我们仔细考虑更改,并且已经清理了架构,那么重构应该很简单。多亏了Angular团队,我们可以使用.toSignal()等函数一步一步地完成这项工作,而且我们不必一步摆脱Zone.js。