强制异步功能同步,而无需等待异步

时间:2019-07-15 13:04:53

标签: javascript asynchronous

我需要强制异步函数同步运行。我的情况真的很复杂,所以我会尝试解释。

我正在开发与服务器通信的Ionic应用程序。

  • 在此应用程序中,我要收费Web服务生成的html页面,并使用createComponent和compileModuleAndAllComponentsAsync创建一个新组件。

  • 在由webservice发送的此html中,有一些脚本标签。这些脚本是其他人定制的javascript,但是它们使用了我们创建的功能。例如,我们创建了一个函数“ createdByUs”。其他人可以使用它制作自定义javascript(以下示例)。

  • “ createdByUs”函数是在Ionic应用程序之前创建的,许多人已经使用它。但是它在离子方面具有另一种行为,并且如果该函数之前是同步的,则该行为是异步的。

  • 现在,我必须针对离子应用程序调整此功能,并且由于自定义脚本是在之前创建的,因此我必须编辑“ createdByUs”。该代码运行良好,只是异步的,因此其余的自定义代码在“ createdByUs”结束之前执行。

  <!-- our function -->
  <script type="text/javascript">
    inIonic = true;
    function createdByUs(){
        if(inIonic){
            new Promise(function(resolve, reject) {
              setTimeout(() => {
                console.log('Promise is created and consumed');
                resolve('Promise is created and consumed');
              }, 5000);
            });
        }else{
            console.log("nice synchronous code");
        }   
    }
  </script>

  <!-- custom functions made by other persons I can not modify -->
  <script type="text/javascript" id="customScript">
    createdByUs();
    console.log("other code that must wait for createdByUs");
  </script>

由于我无法修改自定义脚本,因此我不能简单地将“ cratedbyus”设置为异步,并在每个环境中使用await。我的问题有解决方案吗?

---编辑 有关该项目的一些精度: 这是一种“页面编辑器”,我们提供了一个图形界面,以及一个供人们定义自定义脚本的区域。我正在开发一个可以显示这些页面并且可以正常运行的应用程序。但是某些功能在Ionic中不起作用,因此我必须重新定义它们。 为了运行离子代码,我在createdByUs中调用了一个离子事件。它工作得很好,除了事件是异步的,而且它还在ngfor中添加了html元素,而当您修改ngfor的数组源时,ionic不会立即创建元素,因此在ngfor中生成html也是异步的。没完没了...

2 个答案:

答案 0 :(得分:4)

不。你不能那样做。如果您可以这样做,则会造成各种问题(例如,var id=eval('window.iframe.frames.frames.jqGridiframe_2c1ee9b8-5434-48da-ae2e-60cf359b4ce2') 回调无法运行以实际解决承诺,因为线程将在等待承诺时被阻塞),因此无法以任何方式完成此操作,并且将来将不可能。


您可能会说

但是为什么没有办法,它在非异步函数中的行为类似于setTimeout,所以正在运行的执行上下文将被存储,从堆栈中删除,然后在诺言解决了?

当然可以做到这一点,但这会破坏函数的运行至完成保证,换句话说,这会使每段代码都不确定,这通常是一件坏事(换句话说:并发修改,乱序执行等。

但是有一个“全局await建议”可以在await函数之外的顶级await上使用

是的,但仅限于顶层,执行顺序仍然是确定性的(所有必需的模块都在模块运行之前完成)。

答案 1 :(得分:0)

您可以创建一些技巧。

按原样运行async函数,但返回promise。然后,一旦诺言解决,就加载另一个脚本。

myPromise.then(() => {
  const script = document.createElement('script')
  script.src = 'path/to/otherScript'
  document.getElementsByTagName('body')[0].appendChild(script)
})