【问题标题】:How to use async function to await user input from onClick?如何使用异步函数等待来自 onClick 的用户输入?
【发布时间】:2021-03-08 03:23:02
【问题描述】:

我正在尝试从外部 api 获取数据,我使用 asyncawait。我想等待来自onClick 函数的用户输入,然后将 url 传递给异步函数并以 json 格式从该 url 获取数据。 OnClick 功能正在运行:

onClick(){
   this.data=(<HTMLInputElement>document.getElementById('data')).value;
    
   return this.url='https://api.url.info/feed/'+this.data
}

当我使用console.log(data2) undefined 时出现下一个错误:加载资源失败:服务器响应状态为 404(未找到)

async getData(){
    var data2=this.url;
    const response=await fetch(this.url);
    this.data=await response.json();
}

ngOnInit(){
    this.getData();
}

HTML

<input type="text" id="data"  value=""/>
<button type="button" (click)="onClick()" id="btn">Search</button>

【问题讨论】:

  • 我不熟悉 angular,但一般的方法是在事件处理程序中调用 fetching 函数。该事件处理程序已经是等待用户输入的方式。关于async/await 特别是:一个promise 只能解析一次,所以它不能代表一个可以多次触发的事件处理程序。
  • 嗨,Santal,我绝对建议您阅读角度文档 angular.io/docs,因为使用 document 访问 DOM 元素不是可行的方法。 Angular 就是专门为此而存在的,它可以简化您的生活并将其抽象出来。 HTTP 层也是如此。 Angular HttpClient 让您可以执行 HTTP 请求,而不是自己执行 fetch
  • @maxime1992 是正确的。如果您与我们分享您的 HTML 模板,我们可以为您提供一个示例,其中包含执行这两项任务的正确 Angular 方式。
  • 我编辑了我的帖子,现在我有了 html 模板
  • 我仍然看不到 ID 等于“数据”的 HTML 元素,这是您尝试访问的内容。

标签: javascript angular async-await


【解决方案1】:

在你的onClick方法中,调用getData()方法,不要在ngOnInit中调用this.getData()。您的代码应如下所示:

onClick(){
    this.data=(<HTMLInputElement>document.getElementById('data')).value;
    const url='https://api.url.info/feed/'+this.data;
    this.getData(url);
  }
async getData(url){
    const response=await fetch(url);
     this.data=await response.json();
  }

【讨论】:

  • 您的示例有点令人困惑,因为您将 URL 传递给getData 并将其分配给this.url,并且您正在访问getData 中的参数和this.url。我建议稍微清理一下以减少混乱。
  • 你说得对。我已经更新了答案。
  • 虽然这可能有效,但我强烈建议您在使用 Angular 时不要这样做。你正朝着与良好实践相反的方向前进。参考我最初的评论
【解决方案2】:

下面我按照 Angular 最佳实践制作了一个可行的解决方案,对代码进行了注释以帮助您更好地理解它。

Demo

模板

<input #yourData id="data" type="text" id="input"  value=""/>
<button type="button" (click)="onClick()" id="btn">Search</button>

组件

import { Component, OnInit, ViewChild, ElementRef } from "@angular/core";
import { HttpClient } from "@angular/common/http";

@Component({ ... })
export class YourComponent implements OnInit {
  data: any; // The api response is going to be stored here
  baseUrl: string = 'https://api.url.info/feed/';

  // You need to import the HttpClientModule on your module (in the AppModule is fine)
  constructor(private http: HttpClient) { }

  // One of the proper ways to access
  // Documentation: https://angular.io/api/core/ViewChild
  @ViewChild("yourData", { static: true }) yourTemplateElement: ElementRef<HTMLInputElement>;

  // Use ngOnInit if the static option is set to true, use ngAfterViewInit otherwise
  async ngOnInit() {
    this.data = await this.getData(this.baseUrl);
  }

  getData(url: string): any {
    // Use the http client service to make http calls.
    // By default it returns an observable but since you want to use
    // the async/await keywords, we need to convert it into a promise
    return this.http.get(url).toPromise();
  }

  async onClick() {
    const urlSegment = this.yourTemplateElement.nativeElement.value;
    this.data = await this.getData(this.baseUrl + urlSegment);
  }
}

【讨论】:

  • 我使用了这个演示并且正在工作,我还有一个问题(如果你想帮助我):我得到了 json 格式的 api 响应,我想使用 reduce 函数来获得一个特定的响应中的值,我收到此错误:TypeError: this.reduce is not a function。
  • 我会尽力提供帮助,但可能需要更多信息。在这种情况下,this 关键字将引用类实例(在您的情况下,是您的组件),并且由于您没有这样的方法,因此会引发该错误。我推断您正在尝试使用数组 reduce 方法,对吗?所以它应该类似于this.data.reduce(...),但由于您想从列表中获取特定值,因此数组find 方法可能更合适。
猜你喜欢
  • 2018-12-24
  • 2023-02-23
  • 1970-01-01
  • 1970-01-01
  • 2021-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-29
相关资源
最近更新 更多