数组突然只有一个元素,而不是三个元素。

huangapple go评论183阅读模式
英文:

Array has suddenly only one element instead of three elements

问题

I fetch data from a server and use therefore a promise to wait till the data is arrived. Now I'm in the situation that if I go to a page and from their back to the other page, the tasks-Array, that I use to emit the customer tasks to an other component, has if I log it three SelectedCustomerTasks-Elements. But if i want to find the one element of the selected customer i only get an array with just one SelectedCustomerTasks-Element.

This is the console output of the this.customerTasks-Array in the function findTasksOfCustomer:

0: {customerId: '418', tasks: Array(1), openTasksAmount: 1}
1: {customerId: '503', tasks: Array(1), openTasksAmount: 1}
2: {customerId: '409', tasks: Array(4), openTasksAmount: 3}

and this is the console output if I iterate through this array in the function findTasksOfCustomer:

{customerId: '418', tasks: Array(1), openTasksAmount: 1}

I haven't experienced such unusual behavior and I don't know why that happens.

This is my code:

private loadTasks() {
  return new Promise((resolve, reject) => {
    var tasks: tasks[] = [];

    this.customers.forEach(async (customer, index) => {
      var tasks = (
        await this._taskClient.getCustomerTasks(customer.customerId).toPromise()
      ).map((x) => JSON.parse(x) as Task);

      var data: SelectedCustomerTasks = {
        customerId: customer.customerId,
        tasks: tasks,
        openTasksAmount: tasks.filter(
          (x) => x.output[0].valueBoolean !== true
        ).length,
      };

      tasks.push(data);

      if (index == this.customers.length - 1) {
        resolve(tasks);
      }
    });
  });
}
public ngOnInit() {
  this.loadTasks().then((tasks: SelectedCustomerTasks[]) => {
    if (tasks.length > 0) {
      this.customerTasks = tasks;
      if (sessionStorage.getItem("customerId")) {
        this.selectedCustomer = this.customers.find(
          (x) => x.customerId == sessionStorage.getItem("customerId")
        );
        if (this.selectedCustomer) {
          this.emitCustomerData(this.selectedCustomer, false);
        }
      }
    }
  });
}
private async emitCustomerData(customer: Customer){
  this.selectedCustomerEvent.emit(this.findTasksOfCustomer(customer));
}
private findTasksOfCustomer(customer: Customer): SelectedCustomerTasks {
  return this.customerTasks.find((x) => x.customerId == customer.customerId );
}

I've debugged the code.

英文:

I fetch data from a server and use therefore a promise to wait till the data is arrived. Now I'm in the situation that if I go to a page and from their back to the other page, the tasks-Array, that I use to emit the customer tasks to an other component, has if I log it three SelectedCustomerTasks-Elements. But if i want to find the one element of the selected customer i only get an array with just one SelectedCustomerTasks-Element.

This is the console output of the this.customerTasks-Array in the function findTasksOfCustomer:

0: {customerId: '418', tasks: Array(1), openTasksAmount: 1}
1: {customerId: '503', tasks: Array(1), openTasksAmount: 1}
2: {customerId: '409', tasks: Array(4), openTasksAmount: 3}

and this is the console output if I iterate through this array in the function findTasksOfCustomer:

{customerId: '418', tasks: Array(1), openTasksAmount: 1}

I haven't experienced such unusual behavior and I don't know why that happens.

This is my code:

  private loadTasks() {
    return new Promise((resolve, reject) => {
      var tasks: tasks[] = [];

      this.customers.forEach(async (customer, index) => {
        var tasks = (
          await this._taskClient.getCustomerTasks(customer.customerId).toPromise()
        ).map((x) => JSON.parse(x) as Task);

        var data: SelectedCustomerTasks = {
          customerId: customer.customerId,
          tasks: tasks,
          openTasksAmount: tasks.filter(
            (x) => x.output[0].valueBoolean !== true
          ).length,
        };

        tasks.push(data);

        if (index == this.customers.length - 1) {
          resolve(tasks);
        }
      });
    });
  }
public ngOnInit() {
    this.loadTasks().then((tasks: SelectedCustomerTasks[]) => {
      if (tasks.length > 0) {
        this.customerTasks = tasks;
        if (sessionStorage.getItem("customerId")) {
          this.selectedCustomer = this.customers.find(
            (x) => x.customerId == sessionStorage.getItem("customerId")
          );
          if (this.selectedCustomer) {
            this.emitCustomerData(this.selectedCustomer, false);
          }
        }
      }
    });
  }
private async emitCustomerData(customer: Customer){
 this.selectedCustomerEvent.emit(this.findTasksOfCustomer(customer));
}
  private findTasksOfCustomer(customer: Customer): SelectedCustomerTasks {
    return this.customerTasks.find((x) => x.customerId == customer.customerId );
  }

I've debugged the code.

答案1

得分: 2

问题在于 resolve(tasks) 在一个 for each 循环内被调用,这意味着在调用 resolve(tasks) 之前,for 循环不必完全运行。这导致了根据异步任务解决的顺序而产生意外行为。

将方法更改为仅在由 this._taskClient.getCustomerTasks(customer.customerId).toPromise() 创建的所有 promise 都解决后再解决问题。在这里,Promise.all(...) 用于收集所有的 promise 并等待它们全部解决。

英文:

Just to complete this question, so it can be closed:

Problem was that the resolve(tasks) was called inside a for each loop, which means that the for loop did not need to run completely through before resolve(tasks) was called. This was leading to an unexpected behavior depending on the order of the asynchronous tasks resolving.

Switching the approach to resolving only after all promises created by this._taskClient.getCustomerTasks(customer.customerId).toPromise() are resolved did the trick. Here Promise.all(...) was used to collect all promises and wait until all of them are resolved.

答案2

得分: 0

  • 你在代码中声明了两个变量 tasks。确保它们包含你期望的数据。也许可以选择不同的名称来更清楚地表示它们是不同的变量。
  • 对象 data 包含一个指向你的变量 tasks 的属性 tasks,但在下面你也将 data 添加到了 tasks 中。我不知道你的用例是什么,但这看起来很可疑。

调试提示:检查所有访问你的 tasks 的地方。其中一个一定会修改数组。记住,一些对数组的操作会修改数组本身,比如 splice,而不是返回一个修改后的数组。

英文:

Just a few things you might want to check:

  • You declare two variables tasks in your code. Make sure they contain the data you expect them to contain. Maybe choose different names for them to make it more clear that they are different variables.
  • The object data contains a property tasks that points to your variable tasks but below you add data to tasks too. I don't know your use case but this looks supicious.

Tip for debugging: Check all places that access your tasks. One of them has to modify the array. Remember that some operations on arrays modify the array itself, like splice, instead of returning a modified array.

huangapple
  • 本文由 发表于 2023年7月3日 16:14:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76602957.html