【问题标题】:Pause javascript tag execution暂停 javascript 标签执行
【发布时间】:2019-02-01 17:56:10
【问题描述】:

我想知道是否有任何方法可以“暂停”脚本执行,直到一个承诺得到解决,然后才继续执行该特定脚本。(我知道我可以使用 .then() 并且在 es6 中我什至可以使用await ,但这不是我要问的)。 我可以像这样实现睡眠功能:

function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}

我可以每秒检查一次承诺状态吗?或者因为 js 是单线程的,这实际上会冻结所有内容?同步等待承诺的任何混乱方式?

编辑: 我的目标是处理这种情况:

function loadScript(src) {
    try {
        var parent = document.getElementsByTagName('head')[0] || document.documentElement;
        var httpRequest = new XMLHttpRequest();
        httpRequest.open('GET', src, false);
        httpRequest.send();
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.text = httpRequest.responseText;
        parent.appendChild(script);
    } catch (e) {}
}

这个函数位于第三方 js 中,现在我可以挂钩 XMLHttpRequest 对象并拦截该调用并使其异步,但这会搞砸一切,有什么想法吗?

【问题讨论】:

  • 你的 sleep 功能实际上会阻塞浏览器并且永远不会结束。
  • @Justinas 它确实会在几毫秒后结束......我的问题是在这个循环运行的时间里,promise 状态可以改变吗?
  • 不,您的代码将比 new Date().getTime() - start 更快地执行 1e7 迭代达到 miliseconds
  • @Justinas 好的,感谢您的洞察力,但问题仍然是一样的,如果我将循环并检查承诺状态并实际“挂起”执行,承诺状态可以改变吗?还是我会永远循环?
  • 糟糕,好像是XY Problem

标签: javascript


【解决方案1】:

你可以这样睡觉:

function sleep(duration) {
  return new Promise(function(resolve, reject) {
    setTimeout(()=> { resolve(0) }, duration);
  })
}

并在需要时使用 await sleep(1000); //miliseconds 调用 sleep ;

【讨论】:

  • 我知道我可以做到,但我实际上要求的是不同的东西,如果你调用这个函数,你会得到一个承诺作为回报,js 将继续执行(我没有异步函数来使用),这不是我需要的
  • 您可以将异步函数 IIFE 与此睡眠函数一起使用。 stackoverflow.com/questions/40745153/…
  • 我认为没有其他方法可以不阻止浏览器吗?我想看看还有没有其他方法。
  • 我将编辑我的问题以添加更多详细信息,我想我不够具体
【解决方案2】:

通常,对于肮脏的黑客攻击,您只需设置一个无限间隔来检查您需要的任何内容,当它变为真时,清除该间隔并调用任何函数以继续执行预期的执行。

【讨论】:

  • 很脏,很容易锁定浏览器
【解决方案3】:

你需要这个吗?

function sleep(delay) {
  var start = new Date().getTime();
  while (new Date().getTime() < start + delay);
}

sleep(2000)

alert('Hello!')

【讨论】:

    【解决方案4】:

    我可以每秒检查一次承诺状态吗?

    如果必须同步则不,只要您的同步脚本正在运行,就不会执行其他代码。

    或者因为 js 是单线程的,这实际上会冻结所有内容?

    如果全部同步,是的,它会冻结所有内容,并且 Promise 不会解析,因为正在检查 Promise 状态的同步脚本正在阻塞。

    同步等待承诺的任何混乱方式?

    不,没有同步方式来等待 Promise 解决。

    承诺不在 JavaScript 上下文中创建多线程。 Promise 让协作式多任务处理变得更容易,尤其是在引入 await/async 之后,但代码仍然是单线程的。

    【讨论】:

    • 很好的答案谢谢!,我可以考虑几个肮脏的黑客来实现这一点我只需要知道我是否在正确的方向,我的想法之一是在 iframe 中执行脚本和劫持 xhr 调用并使其异步并在主窗口中调用异步 xhr 并冻结 iframe 窗口,直到我的承诺解决,我可以这样做吗?
    • @avidahan 尝试做这样的 hack 看起来你的设计真的很糟糕,所以i just need to know if i'm in the right direction,必须回答 不,你肯定走错了方向。您会发现任何允许某种同步多任务处理的解决方案肯定会因浏览器更新而失败。所以你真的应该停下来寻找这样的解决方案,你应该修复代码的另一部分。
    • 正如我在编辑中提到的,这不是我的设计,代码来自第三方 js,我只想在不损坏代码的情况下消除同步 xhr
    【解决方案5】:

    您正在寻找这样的东西吗?抱歉,我没有完全理解您的问题。

    var promise = new Promise((res, rej) => $.getJSON( "https://jsonplaceholder.typicode.com/todos/1", res, rej))
    
    while(promise.status === 'Pending') { // this waits for the promise
      continue;
    }
    
    promise.then(console.log)
    &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多