简体   繁体   中英

How to create a async timeout error handler in feathers?

How do I create a async-function timeout error handler as a hook in feathers that resides in the service file to handle promises in hooks?

Post created specifically as suggested by @Bergi on my previous question

If you are looking to implement a generic async-function timeout (for promises failing to fulfill for whatever reason) as a featherjs hook, you might want to ask a new (different!) question about specifically that.

I need a function that would be added to the database.hooks.js file (like the errorhandler in the example docs) that would handle exceptions (that cause timeouts) caused by hooks similar to get-database-by-id.js without changing the code in get-database-by-id.js:

get-database-by-id.js

const errors = require('@feathersjs/errors');

module.exports = function (options = {}) {
  return async context => {
    let promise = new Promise((resolve,reject) => { 
                    context.app.service('database').find({
                query: {"id":context.data.id}
                }).then(result => {

                      resolve(result.data[0].data)
                                           // console: error: Unhandled Rejection at: Promise 
                                           //browser:  hangs

            });
    });
    let result = await promise;
    if (result) {
        return context;
    }

  };
};

database.hooks.js (with example errorhandler from docs, does not work with promises)

const { authenticate } = require('@feathersjs/authentication').hooks;

const getDatabaseById = require('../../hooks/get-database-by-id');

const errors = require('@feathersjs/errors');

const errorHandler = ctx => {
  if (ctx.error) {
    const error = ctx.error;
    if (!error.code) {
      const newError = new errors.GeneralError("server error");
      ctx.error = newError;
      return ctx;
    }
    if (error.code === 404 || process.env.NODE_ENV === "production") {
      error.stack = null;
    }
    return ctx;
  }
};


module.exports = {
  before: {
    all: [ authenticate('jwt')],
    find: [],
    get: [],
    create: [
      getDatabaseById,
    ],
    update: [],
    patch: [],
    remove: []
  },

  after: {
    all: [],
    find: [],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
  },

  error: {
    all: [errorHandler],
    find: [],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
  }
};

If featherjs find returns a promise, then there's no need to wrap it in one.

But I think I understand the question to mean that featherjs is broken in the sense that it doesn't reject or resolve on a missing id, and you'd like to force a resolution after a reasonable wait time. If I understand that correctly, you can implement your own timeout with Promise.race()

// find with the given id, or reject after quitAfter milliseconds
async function findById(id, quitAfter) {
  let timer = new Promise(function(resolve, reject) {
    setTimeout(reject, quitAfter, 'timeout exceeded');
  });
  let query = context.app.service('database').find({
    query: { "id": id }
  });
  return Promise.race([timer, query]);
}

Your query function return a promise, then you do not need wrap it into a new Promise. And I hope you already install error hook, the hook will catch all errors which have been thrown from handler function.

In handle function, you just do your business, no need to take care exception errors.

module.exports = function (options = {}) {
  return async context => {
    const response = await context.app.service('database').find({
      query: { "id": context.data.id }
    });

    const result = response.data[0].data;
    if (result) {
      // Maybe you have to store `result` to context object,  like
      // context.result = result;
      return context;
    }
    return null;
  };
};

In your case, maybe you will get back and error on your client, and you can guest the reason why your code did not work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM