Error: Can't wait without a fiber when using .find().fetch()

I’m using socket.io to emit and receive messages. Heres some code:

Meteor.startup(() => {
    io.on('connection', function(client){
		client.on('widgetMessage', function(data) {
			//check if that name exists in our db
			if (Meteor.users.find({'profile.website': 'example.com'}).fetch()) {
  				// element does exist in array
  				console.log("A profiles website has been found!")

			} else {
				//not found in array
				console.log("That website was not found!")
			}	
		});
	});
});

I’m getting an Error: Can't wait without a fiber when calling Meteor.users.find().fetch(). Now I assume this has something to due with Fibers and the async nature of both meteor and socket.io. How can I fix this? From my searches, I’ve seen recommendations for wrapAsync(), bindEnvironment(), or importing the fibers package and doing something like the following: http://stackoverflow.com/a/23164860/3917064

Because of this i’m unsure on what to use. How can I properly fix this issue?

Try to put it in an autorun statement, returning the value out of the async code and setting a reactive variable, and do the find/fetch outside of the async code.

If it’s in the server, sorry just realized then you wrap all of the asynchronous code in the wrapper and return out of it as quickly as possible, only doing the non meteor operations in the callback.

I’ll look into that.

I managed to get it working doing the following:

Fiber(function() {
                if (Meteor.users.find({'profile.website': url}).fetch().length > 0) {
	  				// element does exist in array
	  				console.log("A profiles website has been found!")

				} else {
					//not found in array
					console.log("That website was not found!")
				}
            }).run();

but i would assume that theres a way to handle it better with Meteor.

Nice, I usually use Async.runSync, from the meteorhacks older async package, but they work the same

You can now just use async/await for this, I think - can someone check?

Meteor.startup(() => {
    io.on('connection', function(client){
		client.on('widgetMessage', async function(data) {
			//check if that name exists in our db
			if (await Meteor.users.find({'profile.website': 'example.com'}).fetch()) {
  				// element does exist in array
  				console.log("A profiles website has been found!")

			} else {
				//not found in array
				console.log("That website was not found!")
			}	
		});
	});
});
1 Like

Don’t think this works.

Promises are not available on Meteor’s collection.find(). However, they are available on the underlying nodejs library, so you could use:

Meteor.startup(() => {
  io.on('connection', function (client) {
    client.on('widgetMessage', async function (data) {
      //check if that name exists in our db
      if (await Meteor.users.rawCollection().find({ 'profile.website': 'example.com' }).toArray()) {
        // element does exist in array
        console.log("A profiles website has been found!")

      } else {
        //not found in array
        console.log("That website was not found!")
      }
    });
  });
});

Note, that uses the toArray() method on the raw cursor instead of the fetch() method on Meteor’s cursor, although in this case I think count() may be a more performant test.