_task.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. var ctx = require('./_ctx');
  2. var invoke = require('./_invoke');
  3. var html = require('./_html');
  4. var cel = require('./_dom-create');
  5. var global = require('./_global');
  6. var process = global.process;
  7. var setTask = global.setImmediate;
  8. var clearTask = global.clearImmediate;
  9. var MessageChannel = global.MessageChannel;
  10. var Dispatch = global.Dispatch;
  11. var counter = 0;
  12. var queue = {};
  13. var ONREADYSTATECHANGE = 'onreadystatechange';
  14. var defer, channel, port;
  15. var run = function () {
  16. var id = +this;
  17. // eslint-disable-next-line no-prototype-builtins
  18. if (queue.hasOwnProperty(id)) {
  19. var fn = queue[id];
  20. delete queue[id];
  21. fn();
  22. }
  23. };
  24. var listener = function (event) {
  25. run.call(event.data);
  26. };
  27. // Node.js 0.9+ & IE10+ has setImmediate, otherwise:
  28. if (!setTask || !clearTask) {
  29. setTask = function setImmediate(fn) {
  30. var args = [];
  31. var i = 1;
  32. while (arguments.length > i) args.push(arguments[i++]);
  33. queue[++counter] = function () {
  34. // eslint-disable-next-line no-new-func
  35. invoke(typeof fn == 'function' ? fn : Function(fn), args);
  36. };
  37. defer(counter);
  38. return counter;
  39. };
  40. clearTask = function clearImmediate(id) {
  41. delete queue[id];
  42. };
  43. // Node.js 0.8-
  44. if (require('./_cof')(process) == 'process') {
  45. defer = function (id) {
  46. process.nextTick(ctx(run, id, 1));
  47. };
  48. // Sphere (JS game engine) Dispatch API
  49. } else if (Dispatch && Dispatch.now) {
  50. defer = function (id) {
  51. Dispatch.now(ctx(run, id, 1));
  52. };
  53. // Browsers with MessageChannel, includes WebWorkers
  54. } else if (MessageChannel) {
  55. channel = new MessageChannel();
  56. port = channel.port2;
  57. channel.port1.onmessage = listener;
  58. defer = ctx(port.postMessage, port, 1);
  59. // Browsers with postMessage, skip WebWorkers
  60. // IE8 has postMessage, but it's sync & typeof its postMessage is 'object'
  61. } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts) {
  62. defer = function (id) {
  63. global.postMessage(id + '', '*');
  64. };
  65. global.addEventListener('message', listener, false);
  66. // IE8-
  67. } else if (ONREADYSTATECHANGE in cel('script')) {
  68. defer = function (id) {
  69. html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function () {
  70. html.removeChild(this);
  71. run.call(id);
  72. };
  73. };
  74. // Rest old browsers
  75. } else {
  76. defer = function (id) {
  77. setTimeout(ctx(run, id, 1), 0);
  78. };
  79. }
  80. }
  81. module.exports = {
  82. set: setTask,
  83. clear: clearTask
  84. };