【问题标题】:Where to place async/await in this case?在这种情况下,将 async/await 放在哪里?
【发布时间】:2021-10-19 08:40:30
【问题描述】:

编辑:

问题不在于 async/await 本身的放置,而是我试图使构造函数异步的事实。


我浏览了文档,阅读了其他问题和答案,但我仍然无法理解要异步的函数,以及在哪里放置等待,以获得我想要的行为。

基本上,我希望构造函数中的console.log(this.data) 注销我获取的数据,但现在它会注销待处理的Promise

我已经尝试了所有我能想到的东西,我总是以退出 Promiseundefined 结束。

我在哪里可以在这些方法中添加 async/await 以使其在构造函​​数中注销获取的数据?

如果我以完全错误的方式处理此问题,请告诉我。


class Apa {
  
  constructor () {
    
    this.ajaxURL = 'https://example.com/api/';
    this.mockParams = {
      title: 'foo',
      body: 'bar',
      userId: 1
    };
    
    this.data = this.getData(this.mockParams).then(xhr => this.data = JSON.parse(xhr.response)).catch(xhr => this.data = {});
    console.log(this.data);
    
  }
  
  getData(params) {
    
    return new Promise((resolve, reject) => {

      let request = this.postAjax(this.ajaxURL, params);
      request.then((xhr) => {
        resolve(xhr);
      }).catch((xhr) => {
        this.errorMessage = 'Ajax request failed: getData()';
        reject(xhr);
      });

    });
    
  }
  
  postAjax(url, data) {
    
     return new Promise((resolve, reject) => {
            var params = typeof data == 'string' ? data : Object.keys(data).map(
                function(k){ return encodeURIComponent(k) + '=' + encodeURIComponent(data[k]) }
            ).join('&');

            var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
            xhr.open('POST', url);
            xhr.onreadystatechange = function() {
                if (xhr.readyState>3 && xhr.status==200) { resolve(xhr); }
            };
            xhr.onerror = () => reject(xhr);
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.send(params);
        });
    
  }
  
}

注意: 我知道这个类不能按原样工作,我不得不用模拟的东西替换真正的 API 端点,但我可以确保你在调用真正的 API 时没有问题。承诺(解决后)确实包含具有正确响应的真正 XMLHttpRequest。

【问题讨论】:

  • 顺便说一句,没有必要在getData 中创建Promise,因为函数this.postAjax 已经返回一个
  • 我不认为构造函数可以是async,所以你将无法使用异步/等待,只需使用承诺。然后就像你已经在你的代码的其余部分中一样
  • @JaromandaX 没错,我尝试异步构造函数时出错
  • 是的,但是 console.log(this.data); 在构造函数中,并且不会“等待”上一行中的承诺解决 - 并且您不能在构造函数中使用 async/await(直接)

标签: javascript promise async-await xmlhttprequest


【解决方案1】:

什么函数可以异步

简单规则:如果函数包含await,则必须标记为async。它改变了函数的语义,使得它的return实际上变成了一个promise的解析,并且没有传统的返回值;它还说它的部分执行(await 之后的那些)最终将在未来执行,而不是在当前任务中。

但是,不能延迟对象的创建(构造函数返回时,必须返回构造好的对象),所以构造函数不能是async

您仍然可以从构造函数中的代码输出this.data,但不能在构造函数执行时输出。

由于构造函数必须是同步的才能构造对象,而AJAX请求必须是异步的(*)才能给出响应时间到达,我'我让你知道

如果我以完全错误的方式处理此问题,请告诉我。


*) 这实际上是不正确的; AJAX 调用可以是同步的(通过将false 作为xhr.open 的第三个参数传递),但这是heavily discouraged

【讨论】:

  • 感谢您的宝贵反馈!那么,如果我只是在构造函数中调用 getData() 方法,然后将 Ajax 调用返回后我想要做的所有事情都放在 .then() 中,以获得 getData() 返回的 Promise 会更好吗?跨度>
  • 是的。任何时候你想使用由 AJAX 获取的数据,这应该从回调中完成,或者在 Promise 链中,或类似的(或者交替检查数据是否可用,如果独立调用,如果它有回退行为不是)。
  • 好的,谢谢!我主要在服务器端处理更多同步代码,所以我认为我一直在努力尝试在 JS 中获得相同的流程。您的意见很有帮助。
  • 是的,总是认为“这将在未来”。如果您有 FedEx 包裹要来,您可以: 听铃声然后取包裹(承诺),告诉他们在包裹到达时告诉您,您会取走(回拨),或者当您想打开时在门廊上出去的包裹,看看它是否在这里,如果它打开它,如果没有,告诉自己要有更多的耐心(在资源周围设置一个警卫)。您不能订购东西并立即打开它。只要您知道现在会发生什么以及将来会发生什么,就应该没有问题。
【解决方案2】:

使用 async/await 在构造函数中的代码中执行您想要的操作的唯一方法是这样

class Apa {

  constructor () {

    this.ajaxURL = 'https://example.com/api/';
    this.mockParams = {
      title: 'foo',
      body: 'bar',
      userId: 1
    };
     (async () => {
       this.data = this.getData(this.mockParams).then(xhr => this.data = JSON.parse(xhr.response)).catch(xhr => this.data = {});
       console.log(this.data);
    })();
  }
  ... etc
}

【讨论】:

    猜你喜欢
    • 2017-12-17
    • 1970-01-01
    • 2019-12-04
    • 2020-03-15
    • 1970-01-01
    • 2014-02-05
    • 2022-01-23
    • 1970-01-01
    • 2013-05-02
    相关资源
    最近更新 更多