_task.js 2.2 KB

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