为什么同步睡眠功能而不是因为里面的诺言异步发? [英] Why is synchronous sleep function not made async by being inside promise?

查看:274
本文介绍了为什么同步睡眠功能而不是因为里面的诺言异步发?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想换我周围的承诺的头,以及如何JavaScript的工作与它的队列中,事件循环等。

我想,如果我把一个慢速同步功能的承诺里,慢同步功能将被委派到后台,我可以使用。然后来对付它当它被完成。

 函数syncSleep(MS){
    VAR结束=新的Date()的getTime()+毫秒。
    VAR开始=新的日期()的getTime()。    同时(开始<末){
      启动=新的日期()的getTime()。
    }
}函数p(){
  返回新希望(函数(解析){
     syncSleep(5000);
     解决(syncSleep完成了!);
  });
}ρ()。然后(功能(多个){
  VAR的div =的document.getElementById('异步');
  div.innerHTML =秒;
});VAR的div =的document.getElementById('同步');
div.innerHTML =这应该立即显示(但事实并非如此)!;

https://jsfiddle.net/7mw6m2x5/

用户界面无响应,而这code,虽然运行。

所以我想知道,有人可以解释什么是怎么回事?承诺是只处理code,它已经是制造成的方式异步?

(如果是这样,怎么做呢?)

我该如何处理慢速同步code时,我不希望它冻结用户界面?我必须用一个网络工作者是什么?

感谢任何澄清。谢谢你。


解决方案

在code按预期工作。

由于Javascript是单线程的,用户界面​​将,而你的循环执行阻塞。

承诺只是为了处理异步code的好方法。在这里看到的介绍:

http://www.html5rocks.com/en/tutorials/es6/promises /

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

要能而其他code在后台执行,以保持UI reponsive,你将需要使用WebWorkers:

https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers

从上面列出的页面引用:

网络工作者提供一个简单的装置,用于web内容在后台线程中运行的脚本。工作线程可以在不与用户接口干扰执行任务。

更新

按照你的意见,我制作的这个小脚本演示阻塞和不阻断方法之间的差异。
有一个在code一些重复,但我认为这是很简单的了解。

\r
\r

函数SETVAL(S){\r
  变种divAsync =的document.getElementById('异步');\r
  VAR innerDiv =使用document.createElement('DIV');\r
  innerDiv.innerHTML = S +'< BR>';\r
  divAsync.appendChild(innerDiv);\r
}\r
\r
\r
功能syncSleep(毫秒){\r
  VAR结束=新的Date()的getTime()+毫秒。\r
  。现在VAR =新的日期()的getTime();\r
  VAR stepBegin =新的日期()的getTime()。\r
  无功步骤= 0;\r
\r
  //这个循环阻塞\r
  //该UI将在循环完成后只刷新\r
  而(现<末){\r
    现在=新的日期()的getTime()。\r
    步长=现在 - stepBegin;\r
    如果(步骤> = 1000){\r
      SETVAL(现在的);\r
      步骤= 0;\r
      stepBegin =现在;\r
    }\r
  }\r
\r
}\r
\r
功能pBlock(){\r
  返回新希望(函数(解析){\r
    syncSleep(3200);\r
    解决(pBlock syncSleep完成了!);\r
  });\r
}\r
\r
\r
功能noBlockUpdate(MS,解析){\r
  VAR结束=新的Date()的getTime()+毫秒。\r
  。现在VAR =新的日期()的getTime();\r
  VAR stepBegin =新的日期()的getTime()。\r
  无功步骤= 0;\r
\r
  功能noBlock(){\r
    现在=新的日期()的getTime()。\r
\r
    //油漆每1000毫秒;\r
    步长=现在 - stepBegin;\r
    如果(步骤> = 1000){\r
      SETVAL(现在的);\r
      步骤= 0;\r
      stepBegin =现在;\r
    }\r
\r
    如果(现<末){\r
      //注意:这是要被调用数千次\r
      //但UI还是会更新每1000毫秒\r
      的setTimeout(noBlock);\r
    }其他{\r
      解决(pNoBlock完成了!);\r
    }\r
  };\r
  noBlock();\r
}\r
\r
功能pNoBlock(){\r
  返回新希望(函数(解析){\r
    noBlockUpdate(3200,解析);\r
    SETVAL(pNoBlock推出!);\r
  });\r
}\r
\r
\r
\r
pNoBlock(),然后(SETVAL)。\r
\r
VAR divSync =的document.getElementById('同步');\r
divSync.innerHTML =这似乎马上!\r
\r
\r
\r
//只是等待4秒钟,这样非阻塞code完成\r
的setTimeout(函数(){\r
  //清除所有的div\r
  。的document.getElementById('同步')的innerHTML ='';\r
  的document.getElementById('异步')的innerHTML ='';\r
\r
  VAR divSync =的document.getElementById('同步');\r
  divSync.innerHTML =这并不会立即显示,只有在阻塞操作完成!;\r
\r
  pBlock(),然后(SETVAL)。\r
},4000);

\r

<!DOCTYPE HTML>\r
< HTML和GT;\r
\r
< HEAD>\r
  <间的charset =UTF-8>\r
  < META NAME =视口CONTENT =WIDTH =设备宽度>\r
  <标题> JS斌< /标题>\r
< /头>\r
\r
<身体GT;\r
\r
  < D​​IV ID =同步>< / DIV>\r
\r
  < D​​IV ID =异步>< / DIV>\r
\r
< /身体GT;\r
\r
< / HTML>

\r

\r
\r

I'm trying to wrap my head around promises, and how JavaScript works with it's queue and event loop etc.

I thought that if I put a slow synchronous function inside a promise, that slow sync function would be delegated to the background and I could use .then to deal with it when it was done.

function syncSleep(ms){
    var end = new Date().getTime() + ms;
    var start = new Date().getTime();

    while (start < end) {
      start = new Date().getTime();
    }
}

function p() {
  return new Promise(function(resolve) {
     syncSleep(5000);
     resolve("syncSleep done!");
  });
}

p().then( function(s) {
  var div = document.getElementById('async');
  div.innerHTML = s;
} );

var div = document.getElementById('sync');
div.innerHTML = "This should appear right away! (but it doesn't)";

https://jsfiddle.net/7mw6m2x5/

The UI is unresponsive while this code runs though.

So I was wondering, can someone explain what is going on here? Are Promises only a way to handle code that is already "made to be" async?

(If so, how is that done?)

How do I deal with slow sync code when I don't want it to freeze the UI? Do I have to use a web worker for that?

Grateful for any clarification. Thanks.

解决方案

The code works as expected.

Since Javascript is single threaded, the UI will block while your loop is executing.

Promises are just a nice way to handle async code. See an introduction here:

http://www.html5rocks.com/en/tutorials/es6/promises/

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

To be able to maintain the UI reponsive while other code is executing in the background, you would need to use WebWorkers:

https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers

Quoting from the page listed above:

"Web Workers provide a simple means for web content to run scripts in background threads. The worker thread can perform tasks without interfering with the user interface."

Update:

following your comments, I crafted this little script to demonstrate the difference between blocking and no-blocking approaches. There is some repetition in the code, but I think it is simple enough to understand.

function setVal(s) {
  var divAsync = document.getElementById('async');
  var innerDiv = document.createElement('div');
  innerDiv.innerHTML = s + '<br>';
  divAsync.appendChild(innerDiv);
}


function syncSleep(ms) {
  var end = new Date().getTime() + ms;
  var now = new Date().getTime();
  var stepBegin = new Date().getTime();
  var step = 0;

  // This loop is blocking
  // The UI will only refresh after the loop completion
  while (now < end) {
    now = new Date().getTime();
    step = now - stepBegin;
    if (step >= 1000) {
      setVal(now);
      step = 0;
      stepBegin = now;
    }
  }

}

function pBlock() {
  return new Promise(function(resolve) {
    syncSleep(3200);
    resolve("pBlock syncSleep done!");
  });
}


function noBlockUpdate(ms, resolve) {
  var end = new Date().getTime() + ms;
  var now = new Date().getTime();
  var stepBegin = new Date().getTime();
  var step = 0;

  function noBlock() {
    now = new Date().getTime();

    // paint every 1000ms;
    step = now - stepBegin;
    if (step >= 1000) {
      setVal(now);
      step = 0;
      stepBegin = now;
    }

    if (now < end) {
      // NB: this is going to be called thousands of times
      // But the UI will still update every 1000 ms
      setTimeout(noBlock);
    } else {
      resolve("pNoBlock done!");
    }
  };
  noBlock();
}

function pNoBlock() {
  return new Promise(function(resolve) {
    noBlockUpdate(3200, resolve);
    setVal("pNoBlock launched!");
  });
}



pNoBlock().then(setVal);

var divSync = document.getElementById('sync');
divSync.innerHTML = "This appears right away!";



// Just wait 4 seconds so the non-blocking code completes
setTimeout(function() {
  // Clear all div's
  document.getElementById('sync').innerHTML = '';
  document.getElementById('async').innerHTML = '';

  var divSync = document.getElementById('sync');
  divSync.innerHTML = "This does not appear right away, only after the blocking operation is complete!";

  pBlock().then(setVal);
}, 4000);

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>

<body>

  <div id="sync"></div>

  <div id="async"></div>

</body>

</html>

这篇关于为什么同步睡眠功能而不是因为里面的诺言异步发?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆