0

У меня есть сценарий, который добавляет продукты в удаленную базу данных с использованием RESTful API в Node.js. Он работает хорошо, но я хотел бы изменить приоритет обработки HTTP-запросов. Вот код, чтобы лучше проиллюстрировать то, что я пытаюсь сделать:Запросить очередь приоритетов в Node.js

step(
    function initializeCategories() { 
     createCategories(products, this); 
    }, 
    function createProducts(err, categoriesHash) { 
     console.log("\nCreating products:"); 
     console.log("=================="); 

     var group = this.group(), 
      productDoneCallback; 

     products.forEach(function (product) { 
      product.categories = categoriesHash[product.category + "/" + product.make + "/" + product.model]; 
      productDoneCallback = group(); 

      step(
       function createProduct() { 
        postProduct(convertToBigCommerceObj(product), this); 
       }, 
       function overwriteProduct(err, product, allowOverwrite) { 
        if (err) { 
         console.log(err); 
        } 

        allowOverwrite = allowOverwrite || false; 

        if (allowOverwrite) { 
         updateProduct(product, this); 
        } else { 
         this(err, product); 
        } 
       }, 
       function addExtraInfo(err, product) { 
        addImage(product, productDoneCallback); 
       } 
      ); 
     }); 
    }, 
    function printStats(err) { 
     if (err) { 
      logError(err); 
     } 

     var endTime = +new Date(), 
      duration = endTime - startTime; 

     console.log("\nFinished after " + (duration/1000/60) + " minutes"); 
     console.log(productsAdded + " Products added successfully"); 
     console.log(productsUpdated + " Products updated successfully"); 
     console.log(productsSkipped + " Products skipped"); 
     console.log("Average time (milliseconds) per product was : " + (duration/totalNumProducts)); 
     console.log("For more information see error log (error.log)"); 
    } 
); 

В этом коде изображение продукта всегда добавляет последним после того как все продукты, которые были добавлены. Это связано с тем, что цикл forEach сразу же отправляет все запросы postProduct в очередь событий узла. После того, как первый продукт будет выполнен, на сервер будет отправлена ​​другая запись, добавленная в конец очереди, чтобы добавить изображение этого продукта. Вместо этого я хотел бы, чтобы эта новая запись плавала в верхней части очереди и была следующей обработанной записью (это не другое сообщение о продукте, которое может подождать).

Я понимаю, что для этого мне нужна очередь приоритетов. Я просто не уверен, как я могу добиться этого в Node и Javascript.

Обновление: после обнаружения реализации PriorityQueue в https://github.com/STRd6/PriorityQueue.js, настоящая проблема заключается в обработке очереди асинхронно каждый раз, когда запрос завершается. Или больше, как каждый раз, когда есть доступный HTTP-канал, который был освобожден, нам нужно взять элемент с наивысшим приоритетом.

+0

Не производите тесты, оценка может быть ошибочной. Используйте [benchmark.js] (http://benchmarkjs.com/), который действительно хорошо разбирается в контрольных данных. –

+0

Вы имеете в виду мою статистику, напечатанную в конце? Это не контрольные показатели, поскольку я не сравниваю разные реализации на самом деле. Я просто хотел узнать, сколько времени потребуется. Также я не вижу, как моя оценка может быть испорчена, и если да, то что? Рамка здесь только что усложнит ситуацию, я скорее буду держать ее простой. Тем не менее, это выглядит как классная рамка :). –

ответ

2

Всякий раз, когда вы слышали «очередь приоритетов», вы должны думать о наличии структуры данных кучи. Это не единственный способ сделать это, но они просты в реализации, и поэтому это хороший первый переход.

См. http://eloquentjavascript.net/appendix2.html для случайной реализации. Они предполагают, что при создании кучи вы передаете функцию, которая берет элемент и возвращает свой приоритет. В вашем случае вы можете хранить такие элементы, как [priority, object], и инициализировать свою кучу wth функцией вроде function (x) {return x[0]}.

+0

Спасибо за комментарий btilly :). Я действительно нашел еще более упрощенную реализацию PriorityQueue, используя и отсортировав массив по адресу: https://github.com/STRd6/PriorityQueue.js. Тем не менее, моя проблема теперь больше связана с асинхронным характером узла и процессом асинхронной обработки очереди. Я не могу просто зацикливаться до тех пор, пока очередь не будет пустой, мне нужно как-то обрабатывать очередь каждый раз, когда элемент был завершен (т. Е. Запрос вернулся с сервера). Я обновлю этот вопрос, чтобы это отразить. –

+0

@ yagudaev Вопрос в том, как имитировать фиксированный пул работников. То, что вы делаете, - это глобальное количество доступных работников, которое начинается с положительного числа. И команда 'launchWorker', которая ничего не делает, если этот счет равен 0, и в противном случае уменьшает счетчик и начинает обработку очереди асинхронно. В конце обработки элемента очереди увеличивайте счетчик. И вызывайте 'launchWorker' каждый раз, когда вы ставите в очередь элемент. Предполагая, что в вашем коде нет ошибок, это приведет к тому, что параллельно будет обрабатываться фиксированное количество элементов. – btilly

+0

Да, я так думаю. Вы имеете в виду что-то вроде: http://journal.paul.querna.org/articles/2010/09/04/limiting-concurrency-node-js/ (первый подход звучит очень похоже на то, что вы описываете). –

Смежные вопросы