Hello everyone i’ve a callback function in one route with Iron Router in my meteor project.
The issue is when i run the path localhost:3000/scraper, the console shows the below message: Error: Can’t wait without a fiber
This code scrape to one page ‘x’.
Router.route('/scraper', function(){
  this.response.setHeader( 'Access-Control-Allow-Origin', '*' );
  this.response.setHeader( 'Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE' );
  this.response.setHeader( 'Access-Control-Allow-Headers', 'Content-Type, X-Requested-With, x-request-metadata' );
  this.response.setHeader( 'Access-Control-Allow-Credentials', true );
  var url = 'https://scholar.google.cl/citations?user= ... &hl=es';
  request(url, function(error, response, html){
    if(!error){
      var $ = cheerio.load(html);
      var json_pre = {  id_usuario: "",
                        autor : "",
                        imagen_usuario: ""
                     };
      $('#gsc_prf_in').filter(function(){
        var data = $(this);
        autor = data.text().trim();
        json_pre.autor = autor;
      })
      $('input[name="user"]').filter(function(){
        var data = $(this);
        id_usuario = data.val();
        json_pre.id_usuario = id_usuario;
      })
      $('#gsc_prf_pup').filter(function(){
        var data = $(this);
        imagen_usuario = data.attr('src');
        json_pre.imagen_usuario = imagen_usuario;
      })
      .....
    }
    var json = JSON.stringify(json_pre, null, 4);
    //************************************************ 
                          //Can't wait without a fiber
      var id_usuario_m = Scrapers.findOne({id_usuario :json_pre.id_usuario });
      if (id_usuario_m) {
        Scrapers.update({id_usuario :json_pre.id_usuario }, {$set: json_pre});
        console.log('Usuario Actualizado');
      } else {
        Scrapers.insert(json_pre);
        console.log('Usuario Insertado')
      }
    //************************************************
  })
  this.response.end('Fin de la scrapeada');
}, {where : "server"});
If someone could to help me, I would be be so grateful. Thanks so much to all.
             
            
              
              
              
            
            
                
                
              
                
           
          
            
            
              What if you make the request callback async?
request(url, async function(error, response, html) {
Explanation: in Meteor (on the server) every async function and every promise.then callback runs in a Fiber automatically.
If that doesn’t work for you, the more traditional way to fix this would be:
request(url, Meteor.bindEnvironment(function (error, response, html) {
Explanation: Meteor.bindEnvironment returns a wrapper function that calls the original function in a Fiber.
             
            
              
              
              4 Likes
            
            
                
                
              
           
          
            
            
              Thanks. your info provide was really usefull for me. This solved my issue.
             
            
              
              
              
            
            
                
                
              
           
          
            
            
              @benjamn what about promise.then callback.
I m having troubles with this method which use twilio api to send text to a number.
new ValidatedMethod({
    name: 'sendSMS',
    validate: null,
    run({employeeId}) {
        return twilio.messages.create({
            to: 'somephonenumber',
            from: 'twilionumber',
            body: '',
        }).then((message) => {
        }).catch((error) => {
            console.error(error);
            console.log(Employees.findOne({_id: employeeId}));
            return Promise.reject(new Meteor.Error(error.status, error.message));
        });
    }
});
I got Error: Can't wait without a fiber on the line console.log(Employees.findOne({_id: employeeId}));
I tried wrapping the catch callback with Meteor.bindEnvironment like this:
new ValidatedMethod({
    name: 'sendSMS',
    validate: null,
    run({employeeId}) {
        return twilio.messages.create({
            to: 'somephonenumber',
            from: 'twilionumber',
            body: '',
        }).then((message) => {
        }).catch(Meteor.bindEnvironment((error) => {
            console.error(error);
            console.log(Employees.findOne({_id: employeeId}));
            return Promise.reject(new Meteor.Error(error.status, error.message));
        }));
    }
});
but the error was not returned to the client.
I also tried to use Meteor.setTimeout inside the catch callback like below:
new ValidatedMethod({
    name: 'sendSMS',
    validate: null,
    run({employeeId}) {
        return twilio.messages.create({
            to: 'somephonenumber',
            from: 'twilionumber',
            body: '',
        }).then((message) => {
        }).catch((error) => {
            console.error(error);
            Meteor.setTimeout(() => {
                console.log(Employees.findOne({_id: employeeId}));
            }, 100);
            return Promise.reject(new Meteor.Error(error.status, error.message));
        });
    }
});
```
now I am getting `Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.`
how should I handle async in catch callback?
             
            
              
              
              
            
            
                
                
              
           
          
            
            
              Twilio uses the q Promise library, which won’t play nicely with fibers. However, one way you can get around this is to refactor your code into ES7 async/await. Maybe something like this:
new ValidatedMethod({
  name: 'sendSMS',
  validate: null,
  async run({ employeeId }) {
    try {
      return await twilio.messages.create({
        to: 'somephonenumber',
        from: 'twilionumber',
        body: '',
      });
    } catch (error) {
      console.error(error);
      console.log(Employees.findOne({ _id: employeeId }));
      throw new Meteor.Error(error.status, error.message);
    }
  },
});
             
            
              
              
              1 Like