簡體   English   中英

使用同步功能更改反應狀態的異步/等待

[英]Async/await with sync func changing react state

我在 React 中遇到async / await函數和更改狀態的問題。 這是我的異步函數,通過單擊按鈕觸發:

async startNewEntry() {
    this.addIssue();
    let issue_id;
    console.log(this.state.timeEntry, "started_timeEntry")
    if (this.state.timeEntry?.issue?.id) {
      issue_id = this.state.timeEntry?.issue?.id;
    } else {
      issue_id = (await this.issueService.list()).data[0]?.id;
    }
    const { data } = await this.timeEntryService.create({
      comments: this.state.timeEntry.comments,
      issue_id,
      spent_on: moment(new Date()).format("YYYY-MM-DD"),
      hours: 0.01,
      activity_id: this.localStorageService.get("defaultActivityId")
    });

在這個函數中,我使用this.addIssue ,它使用this.createIssue ,它改變了我的類組件狀態:

addIssue() {
    this.projectService.list([]).then(response => {
      response.data = response.data.filter((x: any) => x.status === 1);
      this.setState(
        {
          activeProjects: response.data
        },
        () => {
          this.createIssue();
        }
      );
    });
  }
  createIssue() {
    this.issueAddService
      .create({
        project_id: this.state.activeProjects[0].id,
        tracker_id: trakerId,
        priority_id: priorityId,
        subject: this.state.timeEntry.comments,
        description: this.state.timeEntry.comments
      })
      .then(response => {
        let timeEntry = this.state.timeEntry;
    timeEntry.issue = response.data;
    this.setState({
      timeEntry
    });

      })
      .catch(error => {
        console.log("error", error);
      });
  }

如您所見,在我的 async 函數中,我擁有新的 State,但實際上 async 函數在我的this.addIssue函數之前工作。 我知道這個問題可能有點奇怪,但先謝謝你!!

如果您希望startNewEntry等到addIssue完成其工作后才addIssue工作,您需要:

  1. addIssue在完成工作后返回一個承諾,並且
  2. 調用時使用awaitawait this.addIssue();

如果您需要startNewEntry來查看更新的狀態,則需要從狀態完成處理程序回調中實現addIssue的承諾,如下所示:

addIssue() {
  // *** Return the promise chain to the caller
  return this.projectService.list([]).then(response => {
    response.data = response.data.filter((x: any) => x.status === 1);
    // *** Create a new promise
    return new Promise(resolve => {
      this.setState(
        {
          activeProjects: response.data
        },
        () => {
          this.createIssue();
          resolve(); // *** Fulfill the promise
        }
      );
    });
  });
}

通常, new Promise是一種反模式,尤其是當您有另一個可以鏈接的new Promise時。 但是在這種情況下,由於您需要等待來自setState的回調(未啟用 promise),因此是合適的。 (


注意對這個問題的評論 我認為你正在設置一個無限循環......

我不是 React 專家,但我不完全理解為什么有很多setState調用散布在這個地方。

如果您將setState留在函數的末尾,那么您可能不需要擔心對它的異步調用正確排序(盡管另一個答案確實顯示了如何實現)。

也許調用一次可能會使代碼更清晰。 歡迎指正。。。

async startNewEntry() {                
    const activeProjects = await fetchActiveProjects()
    const issue = await this.createIssue()         
    const timeEntry = await createTimeEntry({ issue, comments: this.state.timeEntry.comments })
    this.setState({ activeProjects, issue, timeEntry })
}

async fetchActiveProjects() {
    const { data } = await this.projectService.list([])            
    return data.filter(({ status }) => status === 1)
}

async createIssue() {
    const { data } = await this.issueAddService.create({
        project_id: this.state.activeProjects[0].id,
        tracker_id: trakerId,
        priority_id: priorityId,
        subject: this.state.timeEntry.comments,
        description: this.state.timeEntry.comments
    })  
    return data        
}

async createTimeEntry({issue, comments}) {        
    const { data } = await this.timeEntryService.create({
         comments,
         issue_id: issue?.id || (await this.issueService.list()).data[0]?.id,
         spent_on: moment(new Date()).format("YYYY-MM-DD"),
         hours: 0.01,
         activity_id: this.localStorageService.get("defaultActivityId")
    })  
    return data
}

您可以通過並行化前兩個異步調用來進一步加快速度:

async startNewEntry() {                
    const [activeProjects, issue] = 
        await Promise.all([fetchActiveProjects(), this.createIssue()])       
    const timeEntry = await createTimeEntry({ issue, comments: this.state.timeEntry.comments })
    this.setState({ activeProjects, issue, timeEntry })
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM