【问题标题】:Promise resolves earlier than expected and not returning an AXIOS call valuePromise 比预期更早地解决并且不返回 AXIOS 调用值
【发布时间】:2021-10-22 09:54:00
【问题描述】:

我正在向快速连续生成多个字符串的服务发出请求。我的问题是因为我不能控制返回字符串的服务进程,所以我必须返回这个服务的承诺。

我想强调一个事实,即我必须返回一个承诺。

现在,我拥有的是 main 函数(handler.ts),它不包含任何业务逻辑,仅包括以下内容:

public static callback: any;

public static async init(configuration, callback): Promise<any> {
     this.callback = callback;
     ...
     return new Promise((resolve, reject) => {
        try {
            const result = await Service.bootstrap(configuration)
            return resolve(result)
        } catch(err) {
            reject(err)
        }
     }
}

此处理程序调用服务,该服务具有执行对 .js 文件的调用的引导函数,该文件从我的计算机获取一些信息,然后返回有关它的字符串。

import loadComputerInformation from 'load.js'

public async bootstrap() : Promise<any> {
      loadComputerInformation();

      function useComputerInfoString() {
            // window.getInfo is generated by loadComputerInformation(), and I can not control 
            // when does it return it, as it generates several strings with rapid succession 
            // and until the function exists, I will not get my string.
            if (typeof window.getInfo !== 'function') {return;}
            const data = window.getInfo();
            if (data.finished) {
              clearTimeout(timeoutId);
              const infoString = data.computerInfo;
              Service.axiosCall(infoString);
            }
          }
          // I have to set an interval to perform the call several times, and until it resolves it
          // it will not stop performing this call.
          const timeoutId = setInterval(useComputerInfoString, 500);
   }
   return;
}

因此,我面临的问题是我的承诺在另一个线程中丢失了,我无法从 Service.axiosCall(infoString) 中返回值,这只是一个标准的 axios调用,但这必然需要 infoString

添加 axios 调用函数以防万一有用。现在,我正在使用传递给 handler.js 的回调来返回 axios 调用,但我希望能够在不需要回调函数的情况下将其包含在 Promise 中

public static async axiosCall(blackbox): Promise<any> {
   await axios.post('https://somecall.com/info', blackbox)
    .then((response) => {  this.callback(element)
                           return element);
     }
}

知道如何解决这个问题吗?

突出显示

请注意 loadComputerInformation() 异步加载 Window.getInfo(),但它不仅仅解析一个值,而是几个,因此我不能等待 Window.getInfo() 因为在开始时它不存在,并且只会返回 undefined

另外,现在,代码已经启动并运行,但它返回值的方式是通过回调而不是作为承诺。

【问题讨论】:

  • init 函数中的 return 语句可以(我建议应该)替换为 return Service.bootstrap(configuration) - 使用承诺解决从返回的 async 函数返回的承诺一个承诺是矫枉过正:)
  • promise 构造函数甚至不是async 所以这也是错误的,但你应该只返回promise 而不是包装它。您也在useComputerInfoString 上点击 TDZ。在被const 声明初始化之前,您不能使用timeoutId
  • 但重要的是,bootstrap 函数在首次调用时会同步返回 undefined。固有的问题似乎是,在任何阶段都不会轮询window.getInfo(); 返回的值,这会在设置data.finished 时变成一个已解决的承诺。尝试修复它(作为读者)失败了,因为帖子中没有关于 useBlackboxString 函数的信息。下一步是承诺window.getInfo() 投票。
  • 您的 init 函数将无法运行 - 您应该会看到错误
  • 你需要将new Promise inside bootstrap 方法。目前,您的 bootstrap 方法没有 return 任何东西,所以您的其他代码无法 await

标签: javascript node.js typescript promise axios


【解决方案1】:

尝试一个 bootstrap 函数,该函数返回的 promise 使用 axios 调用返回的 response 解析。

这个建议(基于帖子中的信息)是 vanilla JavaScript,用于演示如何解决问题。显然需要修改以将其集成到应用程序中:

 const bootstrap = () => new Promise( resolve => {
    loadComputerInformation();
    let state = "load";
    const timer = setInterval( ()=> {
       if( state == "load") {
           if( typeof window.getData != "function") {
                return;
           }
           state = "get";
       }
       let data;
       if( state == "get") {
           data = window.getData();
           if(!data.finished) {
               return;
           }
           // state = "request";
       }
       clearInterval(timer);
       resolve( axios('post', "https:example.com/info", data.computerInfo) );

    }, 100); // 1/10th second?
};

请注意,此答案已修改为使用状态机等待getData 异步加载,然后等待调用getData 以返回具有finished 属性的数据对象,然后再解析与 axios 调用返回的承诺一起返回的承诺 - 第一个答案更简单,直到它需要等待 getData 代码异步加载。

问题的背后隐藏着一个可能不得不因代码债务而被注销的问题:JavaScript 是事件驱动的。 loadComputerInformation 似乎是为了对其结果进行轮询而编写的。很难想象一个合理的理由让它处于那种状态。

【讨论】:

  • 谢谢!在返回语句的失败混合和您给我的poll 上下文之间,我能够发现我的错误。现在我成功地返回了一个承诺!
猜你喜欢
  • 1970-01-01
  • 2019-06-15
  • 2019-03-11
  • 2021-09-19
  • 1970-01-01
  • 2018-10-04
  • 1970-01-01
  • 2019-06-26
相关资源
最近更新 更多