Есть ли альтернатива для рекурсивного подхода, который я использую здесь, в node.js? - PullRequest
0 голосов
/ 11 января 2019

Я реализовал рекурсивную функцию в requestHandler, который я сделал для сериализации запросов API, а также чтобы убедиться, что конечная точка в данный момент не запрашивается. Чтобы убедиться, что конечная точка в данный момент не запрашивается, я добавляю ее в Set и проверяю ее с помощью условных выражений.

Проблема в том, что этот рекурсивный подход потребляет довольно много памяти, когда много запросов выполняется к одной и той же конечной точке. Можно ли как-нибудь уменьшить объем памяти и производительность? Я хотел бы услышать любой альтернативный подход, который я мог бы использовать вместо рекурсии. Ниже вы можете найти мой код.

async request(endpoint, domain, method, headers, query, body, attachments) {
    const requestURL = `${(domain === "discord") ? this.discordBaseURL :
        (domain === "trello") ? this.trelloBaseURL : domain}/${endpoint}`;

    if (this.queueCollection.has(endpoint) === false) { // queueCollection is the Set in which I store endpoints that are currently being requested by my requestHandler.
        this.queueCollection.add(endpoint);
        const response = await this.conditionalsHandler(endpoint, requestURL, method, headers, query, body, attachments);
        this.queueCollection.delete(endpoint);
        return response;
    }
    else {
        const response = new Promise((resolve) => {
            setTimeout(() => {  // https://stackoverflow.com/a/20999077
                resolve(this.request(endpoint, domain, method, headers, query, body, attachments)); // This is where I make the method recursive to call itself back until the endpoint is no longer in the queueCollection Set.
            }, 0);
        });
        return response;
    }
}

1 Ответ

0 голосов
/ 11 января 2019

Да, вы можете удалить рекурсию, сделав queueCollection a Map<string, Promise> вместо Set<string> и вместо асинхронного рекурса и опроса очереди, пока она не станет пустой, при необходимости выполните цепочку запроса до конца очереди, если это существует так:

async request(endpoint, domain, method, headers, query, body, attachments) {
  const requestURL = `${(domain === "discord") ? this.discordBaseURL :
    (domain === "trello") ? this.trelloBaseURL : domain}/${endpoint}`;

  // get existing queue or create a new one
  const queue = this.queueCollection.get(endpoint) || Promise.resolve();
  // schedule request on the tail of the queue
  const request = queue.then(
    () => this.conditionalsHandler(endpoint, requestURL, method, headers, query, body, attachments)
  );
  // prevent errors from propagating along the queue
  const tail = request.catch(() => {});

  // enqueue the request
  this.queueCollection.set(endpoint, tail);

  try {
    // propagates error handling to consumer
    // waits for request to settle before executing finally block
    return await request;
  } finally {
    // only remove promise from Map if this settled request is at the tail of the queue
    if (this.queueCollection.get(endpoint) === tail) this.queueCollection.delete(endpoint);
  }
}

Этот подход позволяет request до throw без разрыва цепочки, поэтому потребитель может обработать ошибку, и все запросы будут по-прежнему выполняться последовательно, независимо от успешности предыдущих запросов, и он всегда будет очищать * 1009. * в последнем ожидающем запросе независимо от того, выбрасывает request. await здесь не является избыточным по этой причине.

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