Tuesday, 17 November, 2020 UTC


Meteor Fibers meet Promises meet Callbacks — A practical guide

We’ve all been there before. You have a native asynchronous JavaScript function you need to use in your Meteor code, or maybe a Meteor function you’d like to invoke in your Meteor-agnostic code. After considerable time, you end up banging your head on the wall after realizing it won’t be as trivial as it first sounded.
Meteor uses these guys called Fibers under the hood to enable asynchronous execution. Fibers come from the time before JavaScript supported native Promises or async-await keywords. Their goal was to enable developers to write asynchronous code that looks synchronous, without a callback and Promise hell. Given their origin, Fibers aren’t too fond of native ES6 Promises. For some use cases, the Meteor framework provides useful utility functions for conversion between Fiber and non-Fiber functions, such as Meteor.wrapAsync or Meteor.bindEnvironment. However, these operate with callback-style asynchronous functions and don’t play too well with ES6 style async-await paradigm.
At Apify, we’ve been fans of Meteor since 2015 when we built our web scraping and automation platform on top of it. Over the years, we’ve encountered exactly these challenges. In this post, we’d like to share how you can deal with these kinds of conversions easily and effectively. Let’s befriend Fibers and Promises once for all!

Example functions

In the following examples, we’ll consider the three functions that all correspond to the same underlying business logic.
ES6 style asynchronous function which returns a promise.
Asynchronous function that accepts a callback as an argument. Note we assume that callback itself accepts 2 arguments, error (or null if no error) and value.
Meteor async function which can be run synchronously (from a developer perspective) in Meteor code thanks to Fiber.
There are six possible directions you can perform conversions between these three functions.
Possible pairwise conversions between Callback, Promise and Fiber style functions


In this section, we show how to perform these six conversions.

Converting Promise to Callback function

In general, it is not recommended to convert an async Promise function to a Callback one in order to avoid callback hell. But if you really need to, you can do it as follows.

Converting Callback to Promise function

For the opposite direction, one can use native util.promisify() in Node.

Converting Callback to Fiber function

The conversion from Callback to Meteor Fiber function is also quite straightforward. Use Meteor.wrapAsync() as follows:

Converting Fiber to Callback function

For the opposite direction, you can use Meteor.bindEnvironment() as follows:

Converting Fiber to Promise function

Quite likely, you are using ES6 promises in your application and you’re most interested in the final two conversions between Promise and Meteor functions. In order to convert from Meteor to a Promise function, you can use Meteor.bindEnvironment() together with creating a new Promise.

Converting Promise to Fiber

For the other direction, you can use this utility to do the trick.
Then, you can use the utility as follows.


For those of you who like pictures like me, the conversions look schematically as follows.
How to perform conversions between Promise, Callback, and Fiber style functions
And finally, for the geeks out there, we close with an example on how to convert Fiber function to itself by first converting it to Callback function, then to Promise function, and finally back to Fiber function again.
Warning: don’t try this at home :P.
So at the end of the day, Promises and Fibers can indeed live side by side, happily ever after!

Meteor Fibers meet Promises meet Callbacks — A practical guide was originally published in Meteor Blog on Medium, where people are continuing the conversation by highlighting and responding to this story.