【问题标题】:Http-Get-Function seems to be called multiple times in one call and always returns an empty arrayHttp-Get-Function 似乎一次调用多次,总是返回一个空数组
【发布时间】:2018-12-10 23:19:12
【问题描述】:

我有一个 RestController 类,我将提交的数据(到该控制器中的 API)保存在一个数组中,并希望它在调用方法 getAllProjects() 时返回数组的所有元素。

我得到了以下控制器:

@RequestMapping("/project")
@RestController
public class ProjectController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private List<ProjectDto> projectList = new ArrayList<ProjectDto>();
    //...
    @GetMapping(value = Constants.GET_ALL_PROJECTS)
    @ResponseBody
    public List<ProjectDto> getAllProjects() {
        this.logger.info("========== Sending following Projects: =========");
        this.projectList.forEach(e -> {this.logger.info(e.getProjectName());});
        return this.projectList;
    }
}

我的 fontend (TS) 执行以下操作:

export class ProjectReceiverService {

constructor(
  private http: HttpClient, 
  private logger: LoggerService
) { }

getAllProjects() : ProjectCreator[] {
    let projectArray: ProjectCreator[];

    @PostMapping(value = Constants.CREATE_NEW_PROJECT)
    public ResponseEntity createProject(@RequestBody ProjectDto project) {
        this.logger.info(project.toString());
        return ResponseEntity.ok(HttpStatus.OK);
    }

    this.http.get('http://localhost:8080/project/getAllProjects', httpOptions).
      subscribe( (res) => {
        this.logger.info(res);
        res['projectList'].forEach( (project) => {
          projectArray.push(project);
        },
        (error) => {
          this.logger.error(error);
        });
      });

    return projectArray;
  }
}

http选项:

export const httpOptions = {
    headers: new HttpHeaders({
        'Content-Type':  'application/json'
    })
}

API 在我的组件的onInit-method 中调用:

 ngOnInit() {
    this.logger.info("init dashboard component");
    this.updateAllProjects();
  }

  updateAllProjects() {
    this.logger.info("Getting all Projects");
    this.allProjects = this.projectReceiverService.getAllProjects();
  }

我的浏览器中的输出是:

init dashboard component
dashboard.component.ts:35 Getting all Projects
create-project.service.ts:22 Response: OK
project-receiver.service.ts:22 []length: 0__proto__: Array(0)
core.js:14597 ERROR TypeError: Cannot read property 'forEach' of undefined
    at SafeSubscriber._next (project-receiver.service.ts:23)

所以看起来这个数组是空的。所以我检查了我的catalina.out 并有点困惑:

2018-12-11 00:02:03.598  INFO 16388 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2018-12-11 00:02:03.634  INFO 16388 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 34 ms
2018-12-11 00:02:35.308  INFO 16388 --- [nio-8080-exec-5] ProjectController  : ========== Sending following Projects: =========
2018-12-11 00:02:35.373  INFO 16388 --- [nio-8080-exec-3] ProjectController  : ProjectName = name; projectNumber = number; projectArea = area
2018-12-11 00:02:39.042  INFO 16388 --- [nio-8080-exec-7] ProjectController  : ========== Sending following Projects: =========
2018-12-11 00:12:10.185  INFO 16388 --- [nio-8080-exec-2] ProjectController  : ProjectName = name; projectNumber = number; projectArea = area
2018-12-11 00:12:10.196  INFO 16388 --- [nio-8080-exec-3] ProjectController  : ========== Sending following Projects: =========
2018-12-11 00:12:19.106  INFO 16388 --- [nio-8080-exec-7] ProjectController  : ProjectName = test; projectNumber = test; projectArea = test
2018-12-11 00:12:19.121  INFO 16388 --- [nio-8080-exec-5] ProjectController  : ========== Sending following Projects: =========
2018-12-11 00:13:00.895  INFO 16388 --- [nio-8080-exec-4] ProjectController  : ========== Sending following Projects: =========

正如您(可能)看到的那样,我只调用了两次 API:一次使用 projectName "name",一次使用 projectName "test"。然而,记录器(以及 API)必须非常频繁地调用,并且属性 projectList 似乎一直在重新初始化。有人能告诉我那里发生了什么吗?为什么如此频繁地调用 API - 我应该如何处理?

编辑:我正在使用 Spring-Boot 和 Angular 7

【问题讨论】:

    标签: angular rest spring-boot


    【解决方案1】:

    Http 是异步的。所以你要返回数组 before 它被设置:

        this.http.get('http://localhost:8080/project/getAllProjects', httpOptions).
          subscribe( (res) => {
            this.logger.info(res);
            res['projectList'].forEach( (project) => {
              projectArray.push(project);
            },
            (error) => {
              this.logger.error(error);
            });
          });
    
        return projectArray;
      }
    

    处理顺序如下:

    1) 订阅者提交http get请求。

    2) return 语句返回空的projectArray

    3) 从http get请求返回数据,调用subscribe方法中的代码。此代码更新项目列表。

    通常,订阅使用该服务的组件是最佳做法。我的代码如下所示:

    我的服务:

      getProducts(): Observable<Product[]> {
        return this.http.get<Product[]>(this.productsUrl)
          .pipe(
            tap(data => console.log(JSON.stringify(data))),
            catchError(this.handleError)
          );
      }
    

    我的组件:

      ngOnInit(): void {
    
        this.productService.getProducts().subscribe(
          products => this.products = products,
          error => this.errorMessage = <any>error
        );
      }
    

    【讨论】:

    • 谢谢。但是当我添加一个新项目并稍后刷新页面时,我应该至少收到一个包含该项目的数组,不是吗?我很困惑,无论何时刷新站点,我都没有收到任何答案。但是,在 Spring-Boot 后端使用 @Autowired 服务解决了这个问题。对于前端,您的解决方案比我的更优雅,所以也感谢您!我仍然有一个问题:tap 是什么?
    • 我在插入你的代码时遇到了以下错误(我暂时忽略了catchError)Type 'Observable&lt;ProjectCreator[]&gt;' is not assignable to type 'ProjectCreator[]'. Property 'length' is missing in type 'Observable&lt;ProjectCreator[]&gt;'
    • 'tap' 允许您在不修改的情况下进入可观察流。它通常用于调试,例如在此示例中记录我们返回的数据。
    • 如果没有看到一些新代码,您看到的新错误将很难解决。考虑用这个新问题创建一个新问题,我们来看看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-29
    • 2017-05-10
    • 1970-01-01
    • 2012-12-20
    相关资源
    最近更新 更多