Await not working with fibers?

I’m trying to use the async/await, but it seems I need to do something more to stay in my fiber. For instance

await somePromise();
const userIds = Users.find({ ... }).fetch();

will throw

Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.

I though that Meteor support of async/await would handle that. What should I change?

Are you definitely using inbuilt Meteor Promises? I’ve had no issues with those, but popular Promise libraries (like Bluebird) don’t play nicely with fibers.

1 Like

I see. I’m using a npm library so I guess no. More precisely I’m doing:

const Things = new Mongo.Collection('edges', { idGeneration: 'MONGO' });
const _things = Things._collection.rawCollection();
const bulk = _things.initializeUnorderedBulkOp();
... add things to do in bulk
await bulk.execute(); // this doesn't work well with the fiber

It seems that the default promise is not fine with Meteor:

const wait = (t) => new Promise((resolve, reject) => {
  setTimeout(resolve, t);
});
await wait(1000);
Users.findOne();

also fails with

Meteor code must always run within a Fiber

What is the Meteor Promises you’re referring to if it’s not the default one Meteor will use? If I replace await by

Meteor.wrapAsync((cb) => wait(1000).then(cb))();

that works but its really really ugly.

As a temporary fix, I’ve written a helper

export const awaitInFiber = (promise) =>
  Meteor.wrapAsync((cb) => promise.then((res) => cb(null, res)).catch((err) => cb(err)))();

So I can do

awaitInFiber(wait(1000));

and that seems to work

Have you tried meteor add promise? The official package from @benjamn for Promise support with Fiber: https://github.com/meteor/promise

I’m striking the same problem right now. I am using meteor add promise already.

I wonder if it has to do that Meteor 1.4.3 (I think) required us to switch to babel-runtime (using Babel transform-runtime plugin) which might be breaking the extension of Promise? Hmmm… that might be it as console.log(Promise.await) logs undefined, and @benjamn’s library should have added that function onto Promise.

I’ve gotten around it for the moment (super ugly I know) by declaring const MPromise = global.Package['promise'].Promise and then using MPromise.await(...) instead of await ..., and removing async off those functions.

Yes I tried. I ran meteor add promise but then am I supposed to do something specific? Because it was not enough to solve the issue for me.

Solved it for my situation. After reading this README all was revealed.

I had the following at the top of my .babelrc:

  "presets": [
    "react",
    "es2015",
    "stage-3"
  ],

Turns out Meteor adds it’s own presets which cover all of these features. As soon as I removed these presets async/await started working. Note: I still have plugins in my .babelrc.

Problem is now, my .babelrc is broken for all other tools reading my code (WallabyJS for example).

In my situation I solved by

  1. Adding meteor promise package
    meteor add promise

  2. After I used promise in that way, (taking your example)

import {Promise} from ‘meteor/promise’;

Promise.await(somePromise());
const userIds = Users.find({ … }).fetch();