【问题标题】:Angular 10 End Point(id) Is Not A FunctionAngular 10 End Point(id) 不是函数
【发布时间】:2022-08-19 14:26:48
【问题描述】:

您好,我的目标是在交易成功后清空购物车。当购物车中有不止一件商品时,它适用于一件商品(id)。

我有一个 forEach 方法,根据文档应该带一个箭头,使用 => typescript 抱怨说预期的\“,\”。我得到一个异常错误 5 is not a function, 5 is the endpoint which is an id that I\'m trying to delete 。我不明白,我将相同的代码放在 onInit 调用的函数中,它工作正常。我把它放在那里只是为了测试目的。但是当我从一个函数调用这个服务时,它会爆炸,抛出一个异常。问题是它仍然会在刷新页面时删除它抱怨的项目的 ID。我根据文档尝试了一个函数,但是我得到所有类型的错误仍然说我需要一个逗号(,)。就我做错的事情而言,有人可以指出我正确的方向吗?我将不胜感激。

下面的代码sn-p:

购物车服务

  deleteCartItems(): Observable<CartItem[]> {
      return this.http.get<CartItem[]>(cartUrl).pipe(
       map((result: any[]) => {
         
         let cartItems: CartItem[] =[];
          
 
         for(let item of result) {
         
            cartItems.push( new CartItem(item.id, item.size, item.product, item.imageUrl ));
              alert(\"whats in item\" + item.id);
              this.cartIdsArray = cartItems.map(item => item.id)
               let id: number = item.id;
               let  endPoints = \"/cart/\" + id;
               //var  endPoints = \"/cart/\";
              this.cartIdsArray.forEach((item.id),this.http.delete(this.url + endPoints).subscribe(data=>{
               console.log(data);
              })
              
      )
             
            
        }
          
         return cartItems;
         
        })
      );
 
         
    }
  • 那不是有效的 TypeScript 代码,它不会编译。
  • 这确实编译了我只是给了你一个代码的 sn-p 来告诉你我在哪里遇到问题,那就是 foreEach 方法
  • 然后你需要提供forEach方法的来源,因为它显然不标准。同名的内置方法只接受一个参数。
  • 我进行了编辑以显示完整的功能,它确实可以编译
  • 一团糟......难以理解的代码。为什么每次迭代都重新填充this.cartIdsArray?这是什么? this.cartIdsArray.forEach((item.id),this.http.delete......从未见过这种代码结构

标签: angular typescript rxjs


【解决方案1】:

10 End Point(id) 不是函数

Syntax of forEach() method

forEach(callbackFn, thisArg)

forEach() 的第二个可选参数是thisArg

我得到一个异常错误 5 is not a function

错误是正确的,因为第一个参数应该是一个函数。它可以用几种不同的语法箭头函数、内联函数或命名函数来指定。

因此,当您将数字 5 作为第一个参数而不是实际函数传递时,Javascript 会正确出错。

为什么调用 API?

第二个参数 thisArg 被评估为 Javascript 表达式,并作为副作用被触发。 查看代码中实际发生的事情的一个小例子。

var arr = [1,2,3,4];
var item = {
  id: 5
}

arr.forEach(item.id, console.log('deletion successful'))

现在,这个问题被理解了,修复它就更容易了。

当购物车中有不止一件商品时,它适用于一件商品(id)。

forEach() 方法被执行时,它会评估导致调用删除 API 的两个参数,并在发现第一个参数不是函数后引发错误。由于未捕获错误,它会停止执行 deleteCartItems() 方法。 cartIdsArray 中的其余项目永远不会得到处理。

重构解决方案 1

  1. 您不需要遍历完整的结果列表,因为已经有一个循环。

  2. 不需要新的 CartItem() 实例。

  3. 创建了很多订阅,导致内存泄漏。 Stackblitz

    deleteCartItems(): Observable<CartItem[]> {
    const cartUrl = 'https://62c41dc97d83a75e39f0d512.mockapi.io/api/v1/cart';
    return this.http.get<CartItem[]>(cartUrl).pipe(
      tap((cartItems: CartItem[]) => {
        cartItems.forEach((cartItem) => {
          this.http
            .delete(this.url + '/cart/' + cartItem.id)
            .pipe(first())
            .subscribe();
        });
        return cartItems;
      })
    );
    

    }

    重构解决方案 2

    我们不需要使用 Array forEach() 方法,而是使用 Array map() 方法 您实际上可以使用 forkJoin() 运算符进行并行 API 调用。此外,实际上不需要 map() 运算符,因为您没有转换结果,tap() 是更好的候选者,因为您想要副作用 Stackblitz

    deleteCartItems(): Observable<CartItem[]> {
        const cartUrl = 'https://62c41dc97d83a75e39f0d512.mockapi.io/api/v1/cart';
        return this.http.get<CartItem[]>(cartUrl).pipe(
          tap((cartItems: CartItem[]) => {
            forkJoin(
              cartItems.map((cartItem) =>
                this.http.delete(this.url + '/cart/' + cartItem.id).pipe(first())
              )
            ).subscribe();
            return cartItems;
          })
        );
      }
    

    重构解决方案 3

    嵌套的subscribe() 仍然很糟糕,可以如下删除。

    Stackblitz

        deleteCartItems(): Observable<CartItem[]> {
        const cartUrl = 'https://62c41dc97d83a75e39f0d512.mockapi.io/api/v1/cart';
        return this.http.get<CartItem[]>(cartUrl).pipe(
          first(),
          mergeMap(cartItems => {
            return forkJoin(
              cartItems.map((cartItem) =>
                this.http.delete<CartItem>(this.url + '/cart/' + cartItem.id).pipe(first())
              )
            )
          })
        )
      }
    

    注意:我将错误处理作为练习,但应该针对实际项目进行。

【讨论】:

  • 嗨,法尔根。我喜欢您处理我的问题的方式,我确实查看了文档以及您解释它的方式,从那时起。当我在没有 item 的情况下执行此操作时,当我将鼠标悬停在它上面时,它说 value is never read。
  • 嗨 Phalgun,由于 id 永远不会被读取,它会一直循环下去,直到它抛出异常。现在我必须弄清楚为什么永远不会读取该值。这当然是根据文档使用箭头功能。
  • 我围绕您通过 API 调用提供的函数创建了一个示例应用程序。 stackblitz.com/edit/angular-ivy-x4poxw?file=src/app/…。我不明白,“当我在没有项目的情况下进行操作时,当我将鼠标悬停在它上面时,它说 value is never read”,你在哪里看到“ value is never read”。如果您可以添加一个您看到“从未读取值”的屏幕截图,那就太好了
  • 嗨,Phalgun,当我将鼠标悬停在 id 上时,我看到了它,但我想出了那部分。我不得不打破我的端点。太感谢了。作为开发人员,我们来到 stackoverflow 是为了与其他开发人员(例如您自己)协作。我正在独自开发一个巨大的应用程序。这个应用程序有几个 api。我有一个 PayPal 也只有按钮。我负责让它与我的购物车一起工作。这是最后一块。我很努力,但学到了很多。再次感谢您,支撑我们的总是小事。我会记住你的名字。耐力是有回报的。
  • 我已经用一些重构的机会更新了答案。您可能想接受答案。
【解决方案2】:

这是一个简化的代码 sn-p(纯 Typescript、模拟数据、没有 Angular 和没有服务调用),我认为这是您想要实现的。专注于循环做了什么以及如何最终重复调用最后一个forEach中的服务。如果我是正确的,那么您可以相应地更改您的代码。

class CartItem {
    id: number;
}

const result = [{ id: 1 }, { id: 2 }] as CartItem[];
const cartItems: CartItem[] = [];

for (let item of result) {
    cartItems.push({ id: item.id });
    console.log("whats in item " + item.id);
    this.cartIdsArray = cartItems.map(item => item.id);
}
this.cartIdsArray.forEach(id => {
    const endPoint = "/cart/" + id;
    console.log(id, endPoint);
});

或者更简单:

class CartItem {
    id: number;
}

const result = [{ id: 1 }, { id: 2 }] as CartItem[];
const cartItems: number[] = [];

for (let item of result) {
    console.log("whats in item " + item.id);
    cartItems.push(item.id);
}
cartItems.forEach(id => {
    const endPoint = "/cart/" + id;
    console.log(id, endPoint);
});

【讨论】:

    【解决方案3】:

    尝试这个

    deleteCartItems() {
      return this.http.get<CartItem[]>(cartUrl).pipe(
          concatAll(),
          map((item) => new CartItem(item.id, item.size, item.product, item.imageUrl)),
          mergeMap((item) => this.deleteCartItemById(item.id).pipe(map(item))),
          toArray(),
      );
    }
    
    deleteCartItemById(id: number) {
      return this.http.delete(`${this.url}/cart/${id}`);
    }
    

    【讨论】:

      猜你喜欢
      • 2020-11-25
      • 2020-12-31
      • 2020-12-30
      • 2013-09-27
      • 2017-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-16
      相关资源
      最近更新 更多