Blog
queueMacroTask in React source code

queueMacroTask in React source code

In this article, we analyze queueMacroTask in React source code.

Although, file and function are named as enqueueTask, it is imported as queueMacroTask. Unlike window.queueMicroTask, there is no function such as window.queueMarcoTask. setTimeout is an example of MacroTask.

Read more about event loop, micro task and macro task.

React’s enqueueTask:

/**
 * Copyright © Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */
let didWarnAboutMessageChannel = false;
let enqueueTaskImpl = null;
export default function enqueueTask(task: () => void): void {
   if (enqueueTaskImpl === null) {
     try {
       // read require off the module object to get around the bundlers.
       // we don't want them to detect a require and bundle a Node polyfill.
       const requireString = ('require' + Math.random()).slice(0, 7);
       // $FlowFixMe[invalid-computed-prop]
       const nodeRequire = module && module[requireString];
       // assuming we're in node, let's try to get node's
       // version of setImmediate, bypassing fake timers if any.
       enqueueTaskImpl = nodeRequire.call(module, 'timers').setImmediate;
       } catch (_err) {
       // we're in a browser
       // we can't use regular timers because they may still be faked
       // so we try MessageChannel+postMessage instead
       enqueueTaskImpl = function (callback: () => void) {
       if (__DEV__) {
         if (didWarnAboutMessageChannel === false) {
           didWarnAboutMessageChannel = true;
           if (typeof MessageChannel === 'undefined') {
             console.error(
             'This browser does not have a MessageChannel implementation, ' +
             'so enqueuing tasks via await act(async () => …) will fail. ' +
             'Please file an issue at https://github.com/facebook/react/issues ' +
             'if you encounter this warning.',
             );
           }
         }
       }
       const channel = new MessageChannel();
       channel.port1.onmessage = callback;
       channel.port2.postMessage(undefined);
     };
   }
  }
  return enqueueTaskImpl(task);
}

This code has comments explaining what it does. There are some tricks we could learn here:

  • How to get around bundlers when you are writing your own enqueque trask.

  • In node env, setImmediate can be used as MacroTask.

  • In browser env, MessageChannel can be used to create a queueMacroTask effect.

This enquequeTask is imported as MacroTask in ReactAct.js and is used as a fallback in case window.queueMicroTask does not exist:

At the following lines:

About me:

Hey, my name is Ramu Narasinga. I study large open-source projects and create content about their codebase architecture and best practices, sharing it through articles, videos.

I am open to work on interesting projects. Send me an email at ramu.narasinga@gmail.com

My Github — https://github.com/ramu-narasinga

My website — https://ramunarasinga.com

My Youtube channel — https://www.youtube.com/@thinkthroo

Learning platform — https://thinkthroo.com

Codebase Architecture — https://app.thinkthroo.com/architecture

Best practices — https://app.thinkthroo.com/best-practices

Production-grade projects — https://app.thinkthroo.com/production-grade-projects

References