Skip to content
This repository has been archived by the owner on Feb 26, 2024. It is now read-only.

Commit

Permalink
feat(scheduling): Support Promise.then() fallbacks to enqueue a micro…
Browse files Browse the repository at this point in the history
…task
  • Loading branch information
vicb committed May 8, 2015
1 parent eef1a59 commit 74eff1c
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 30 deletions.
104 changes: 91 additions & 13 deletions dist/zone-microtask.js
Original file line number Diff line number Diff line change
Expand Up @@ -1111,21 +1111,9 @@ module.exports = {

}).call(this,{},typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],4:[function(require,module,exports){
(function (global){
'use strict';

// TODO(vicb) asap implementation should work if Promise is not available
// es6-promise has fallbacks

if (typeof Promise === "undefined" || Promise.toString().indexOf("[native code]") === -1) {
throw new Error('Promise is not available natively !')
}

var resolvedPromise = Promise.resolve(void 0);

function asap(fn) {
resolvedPromise.then(fn);
}

function scheduleMicrotask(fn) {
asap(this.bind(fn));
}
Expand All @@ -1139,6 +1127,96 @@ module.exports = {
addMicrotaskSupport: addMicrotaskSupport
};

// TODO(vicb): There are plan to be able to use asap() from es6-promise
// see https://github.com/jakearchibald/es6-promise/pull/113
// for now adapt code from asap.js in es6-promise
// Note: the node support has been dropped here

// TODO(vicb): Create a benchmark for the different methods & the usage of the queue
// see https://github.com/angular/zone.js/issues/97

var hasNativePromise = false;
var len = 0;

if (typeof Promise ==! "undefined" && Promise.toString().indexOf("[native code]") !== -1) {
hasNativePromise = true;
}

function asap(callback) {
queue[len] = callback;
len += 1;
if (len === 1) {
scheduleFlush();
}
}

var browserWindow = (typeof global.window !== 'undefined') ? global.window : undefined;
var browserGlobal = browserWindow || {};
var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;

// test for web worker but not in IE10
var isWorker = typeof Uint8ClampedArray !== 'undefined' &&
typeof importScripts !== 'undefined' &&
typeof MessageChannel !== 'undefined';

function useMutationObserver() {
var iterations = 0;
var observer = new BrowserMutationObserver(flush);
var node = document.createTextNode('');
observer.observe(node, { characterData: true });

return function() {
node.data = (iterations = ++iterations % 2);
};
}

// web worker
function useMessageChannel() {
var channel = new MessageChannel();
channel.port1.onmessage = flush;
return function () {
channel.port2.postMessage(0);
};
}

function useSetTimeout() {
return function() {
setTimeout(flush, 1);
};
}

function usePromise() {
var resolvedPromise = Promise.resolve(void 0);
return function() {
resolvedPromise.then(flush);
}
}

var queue = new Array(1000);

function flush() {
for (var i = 0; i < len; i++) {
var callback = queue[i];
callback();
queue[i] = undefined;
}

len = 0;
}

var scheduleFlush;
// Decide what async method to use to triggering processing of queued callbacks:
if (hasNativePromise) {
scheduleFlush = usePromise();
} else if (BrowserMutationObserver) {
scheduleFlush = useMutationObserver();
} else if (isWorker) {
scheduleFlush = useMessageChannel();
} else {
scheduleFlush = useSetTimeout();
}

}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],5:[function(require,module,exports){
(function (global){
'use strict';
Expand Down
Loading

0 comments on commit 74eff1c

Please sign in to comment.