Хранение обещания JavaScript - PullRequest
0 голосов
/ 13 декабря 2018

Я довольно новичок в Node и решил преобразовать одну из моих баз кода в async / await.Преобразование обратных вызовов в Async / await было относительно простым процессом, но я столкнулся с проблемой, когда я храню обратный вызов в очереди.

    this.on("request", (requestString, response) => {
        // Check if there are no available workers
        if (this.freeWorkers.length === 0) {
            logger.info("Workers are busy please wait...");
            this.queue.push([requestString, response]);
        } else {
            const worker = this.freeWorkers.pop();
            /* Run the worker and send back the response */
            worker.run(requestString, response, data => {
                response(data); 
            });
        }
    });

Проблема, с которой я сталкиваюсь, заключается в том, что я не хочу выходить из асинхронного / ожидающего использования нового Promise (разрешить, отклонить), если мне не нужно.Вышеприведенная версия работает хорошо, потому что другое событие «возврат» завершит сохраненный обратный вызов, когда есть запрос в this.queue.Асинхронная версия выглядит следующим образом:

async request (requestString) {
    if (this.freeWorkers.length === 0) {
        logger.info("Workers are busy please wait...");
        this.queue.push([requestString, /* How do I store the promise here? */]);
    } else {
        logger.info("sending request...");
        const worker = this.freeWorkers.pop();

        /* Run the worker and send back the response */
        return await worker.run(requestString);
    }
}

Вопрос в том, как изнутри функции асинхронности / ожидания можно сохранить обещание в this.queue ()?

Редактировать: Добавление некоторых дополнительных деталей в соответствии с просьбой, чтобы, надеюсь, устранить некоторую путаницу.

«API», если можно так назвать его, из древнего программного обеспечения IBM от 1982 года, которое моя компания использует для внутреннего использования.this.on("request" испускается из другого класса в моем API.Если вам интересно, вот как сейчас выглядит работник:

/**
 * Class Worker is a simple class with only a constructor and 1 run method
 * sends a plain TCP request
 * Uses a callback response and closes the connection
 * */
class Worker {
/**
 * Sets variables that it will use in the future
 *
 * @param {number} port
 * @param {TracsRequest} eventEmitter
 * */
constructor(port, eventEmitter) {
    this.host = /* redacted */;
    this.port = port;
    this.emitter = eventEmitter;
    this.lastRequest = null;
    this.lastResponse = null;
}

/**
 * Takes in a formatted request string and opens a TCP Port to parse the request
 *
 * @param requestString
 * @param response
 */
async run(requestString) {
    this.lastRequest = requestString;
    this.lastResponse = response;
    const socket = new net.Socket();
    let tempBuffer = null;
    const client = socket.connect(
        this.port,
        this.host,
        () => {
            client.write(requestString);
        }
    );


    let socketPromise = new Promise((resolve, reject) => {
        /**************************
         * SOCKET EVENT LISTENERS *
         **************************/
        // store the incoming data
        client.on("data", data => {
            tempBuffer += data;
        });

        // client has finished respond with the data
        client.on("end", () => {
            logger.info("the client has finished");

            this.emitter.emit("return", this);
            client.destroy();

            tempBuffer = tempBuffer.substring(4);
            resolve(tempBuffer);
        });

        // Client has responded with an error send the worker back to the Request class
        client.on("error", error => {
            logger.error(`OHH snap he's dead Jim:${error}`);
            reject(error);
        });
    });

    return await socketPromise;
}

} `

Ответы [ 2 ]

0 голосов
/ 13 декабря 2018

После еще нескольких копаний я смог придумать рабочий пример асинхронности.В этом примере используется new Promise(), который, я считаю, является наилучшим способом достижения того, о чем я просил, поскольку async / await не имеет функции разрешения, которую я могу сохранить в массиве.

async request (requestString) {
    let data = false;
    try {
        if (this.freeWorkers.length === 0) {
            logger.info("Workers are busy please wait...");
            let queuePromise = new Promise((resolve, reject) => {
                this.queue.push([requestString, resolve, reject]);
            });

            /* await for the queue to run this request */
            data = await queuePromise;
        } else {
            logger.info("sending request...");
            const worker = this.freeWorkers.pop();

            /* Run the worker and send back the response */
            data = await worker.run(requestString);
        }   
    } catch (error) {
        logger.error("Something went wrong in request");
        throw error;
    }

    return data;
}

Благодарядругой ответ на этот вопрос, чтобы привести меня в правильном направлении!Я также отформатировал функцию с помощью try / catch, чтобы ошибки не обрабатывались.

0 голосов
/ 13 декабря 2018

Вы не показали нам код, который повторно добавляет рабочих в пул и / или извлекает их из рабочей очереди, которую я назову replenish.Что бы ни происходило, нужно будет либо вызвать функцию (response), либо выполнить обещание (предположительно, вызвав resolve, сохраненный из конструктора new Promise).В конце концов, даже если вы можете сохранить Обещание, идея заключается в том, что вы не можете разрешить его внешне только со ссылкой на Обещание - вам действительно нужно сохранить ссылку на resolve, чтобы изменитьстатус Обещания.

Я бы позвонил new Promise() в request, сохранил функцию resolve и добавил ее в очередь.Это означает, что вашей функции-заменителя работника и инспектора очереди replenish не нужно иметь дело с обещаниями, она просто должна иметь дело с вызовом функции по завершении работы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...