[Fixed] angular 10 subscribe of http.get is not working

Issue

I created backend in Node.js and frontend in angular2+. I want to do a simple todo-list. I made a GET, POST, and DELETE methods, and these works correctly. The problem is when I subscribe my getTodos function, I not getting any updates when todosList is changed by POST or DELETE in the meanwhile.

Here is the code for todo.service.ts

    import { Injectable } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    import { Observable } from 'rxjs';
    import { Todo } from '../models/todo.model';

    @Injectable()
    export class TodoService {
      constructor(private http: HttpClient) { }

      getTodos(): Observable<Todo[]> {
        const baseUrl = 'http://localhost:3000/'
        const todoUrl = 'api/todo'
        return this.http.get<Todo[]>(baseUrl + todoUrl)
      } 
    }

Have typescript code app.component.ts

    const baseUrl = 'http://localhost:3000/'

    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.scss'],
      providers: [ TodoService ]
    })
    export class AppComponent implements OnInit {
      title = 'todo';
      taskHeader = ['User', 'Todo', 'Is done', 'Has attachment']
      todos: Todo[];

      constructor(private http: HttpClient, private todoService: TodoService) {}

      ngOnInit() {
        this.todoService.getTodos()
          .subscribe((res) =>  {this.todos = res
          console.log('this.todos', this.todos)}
        )
      }

      send(data) {
        const addUserUrl = 'api/todo'
        
        let addUserHeaders = new HttpHeaders().append('Content-Type', 'application/json');

        const todo: Todo = {
          userName: 'test',
          todo: data,
          isDone: true,
          hasAttachment: false
        }
        
        this.http.post(baseUrl + addUserUrl, todo,  {headers: addUserHeaders, responseType: 'text'}).subscribe((x) => console.log(x) )
      }  
      
      deleteTask(todoId) {
        const addUserUrl = 'api/todo'
        this.http.delete(`${baseUrl}${addUserUrl}/${todoId} `, {responseType: 'text'}).subscribe((s) => {
          console.log(s);
        })
      }
    }

Here is api.controller.js

    module.exports = (app) => {
      app.use(bodyParser.json())
      app.use(bodyParser.urlencoded({ extended: true }))

      app.get('/api/todo', (req, res) => {
        Todos.find({}).then(function (todos) {
          res.send(todos);
        });
      })

      app.post('/api/todo', (req, res) => {
        if (req.body.id) {
          Todos.findByIdAndUpdate(req.body.id, {
            todo: req.body.todo, isDone:
            req.body.isDone, hasAttachment:
            req.body.hasAttachment
          }, 
          (err, todo) => {
            if (err) throw err
            res.send('Post Success')
          })
        }

        else {
          const newTodo = Todos({
            userName: req.body.userName,
            todo: req.body.todo,
            isDone: req.body.isDone,
            hasAttachment: req.body.hasAttachment
          })
          newTodo.save((err) => {
            if (err) throw err
            res.send('Post Success')
          })
        }    
      });

      app.delete('/api/todo/:id', (req,res) => {
        Todos.findByIdAndRemove(req.params.id, (err) => {
          if (err) throw err
          res.send('Delete Success')
        })
      })
    }

Solution

Subscribe doesn’t work the way you think. If you subscribe to getTodos the request gets sent once, you get the response and that’s it. There is no connection anymore that would get notified about any change in your database when there is a post/delete request.

You have several options:

  • whenever you make a post/delete request instead of sending Post Success or Delete Success as a response you send the database content.
  • after a successful post/delete request you modify the data in your frontend
  • you use websockets as a steady connection between your frontend and backend. this options comes close to how you think subscribe works

Personally I would implement the first or second option.

Leave a Reply

(*) Required, Your email will not be published