Сборка V8 массива строк асинхронно

Я строю модуль узла для взаимодействия с libapt так что я могу перечислить и контролировать установленные пакеты. Я начал просто с реализации функции для получения имени каждого установленного пакета. Я уже ударил стену.

У меня в настоящее время есть этот код:

#include <apt-pkg/init.h>
#include <apt-pkg/cachefile.h>
#include <apt-pkg/pkgcache.h>
#include <node.h>
#include <v8.h>

using namespace v8;

typedef struct AsyncData {
Persistent<Function> callback; // callback function
Handle<Array> packageList;         // array of package names
} AsyncData;void AsyncWork(uv_work_t *req) {
AsyncData *asyncData = (AsyncData *)req->data;

asyncData->packageList = Array::New();

size_t i = 0;
for (pkgCache::PkgIterator package = cache->PkgBegin(); !package.end(); package++) {
if(package->CurrentVer == 0) continue;
asyncData->packageList->Set(i++, String::New(package.Name()));
}
}

void AsyncAfter(uv_work_t *req) {
HandleScope scope;

AsyncData *asyncData = (AsyncData *)req->data;

Handle<Value> argv[] = {
Null(),
asyncData->packageList
};

TryCatch try_catch;
asyncData->callback->Call(Context::GetCurrent()->Global(), 2, argv);
if (try_catch.HasCaught())
node::FatalException(try_catch);

asyncData->callback.Dispose();

delete asyncData;
delete req;
}

Handle<Value> InstalledPackages(const Arguments& args) {
HandleScope scope;

uv_work_t *req = new uv_work_t;
AsyncData *asyncData = new AsyncData;
req->data = asyncData;

asyncData->callback = Persistent<Function>::New(Local<Function>::Cast(args[1]));

uv_queue_work(
uv_default_loop(),
req,                          // work token
AsyncWork,                    // work function
(uv_after_work_cb)AsyncAfter  // function to run when complete
);

return scope.Close(Undefined());
}

void Initialize(Handle<Object> exports) {
pkgInitConfig(*_config);
pkgInitSystem(*_config, _system);
// function hello();
exports->Set(String::NewSymbol("getInstalledPackages"), FunctionTemplate::New(InstalledPackages)->GetFunction());
}

NODE_MODULE(apt, Initialize)

Основная проблема заключается в том, что вы не можете использовать никакие объекты V8 в потоке, кроме основного цикла событий. Это означает, что я получаю ошибку в коде выше. Поэтому я изменил свой код следующим образом:

#include <apt-pkg/init.h>
#include <apt-pkg/cachefile.h>
#include <apt-pkg/pkgcache.h>
#include <node.h>
#include <v8.h>

using namespace std;
using namespace v8;

typedef struct AsyncData {
Persistent<Function> callback; // callback function
vector<string> packageList; // array of package names
} AsyncData;void AsyncWork(uv_work_t *req) {
AsyncData *asyncData = (AsyncData *)req->data;

pkgCacheFile cache_file;
pkgCache* cache = cache_file.GetPkgCache();

for (pkgCache::PkgIterator package = cache->PkgBegin(); !package.end(); package++) {
// If the current package has Version of 0, its no installed
if(package->CurrentVer == 0)
continue;

asyncData->packageList.push_back(package.Name());
}
}

void AsyncAfter(uv_work_t *req) {
HandleScope scope;

AsyncData *asyncData = (AsyncData *)req->data;

Handle<Array> packageArray = Array::New(asyncData->packageList.size());

for(size_t i = 0; i < asyncData->packageList.size(); i++) {
packageArray->Set(i, String::New(asyncData->packageList[i].c_str()));
}

Handle<Value> argv[] = {
Null(),
packageArray
};

TryCatch try_catch;
asyncData->callback->Call(Context::GetCurrent()->Global(), 2, argv);
if (try_catch.HasCaught())
node::FatalException(try_catch);

asyncData->callback.Dispose();

delete asyncData;
delete req;
}

Handle<Value> InstalledPackages(const Arguments& args) {
HandleScope scope;

uv_work_t *req = new uv_work_t;
AsyncData *asyncData = new AsyncData;
req->data = asyncData;

asyncData->callback = Persistent<Function>::New(Local<Function>::Cast(args[0]));

uv_queue_work(
uv_default_loop(),
req,                          // work token
AsyncWork,                    // work function
(uv_after_work_cb)AsyncAfter  // function to run when complete
);

return scope.Close(Undefined());
}

void Initialize(Handle<Object> exports) {
pkgInitConfig(*_config);
pkgInitSystem(*_config, _system);
// function hello();
exports->Set(String::NewSymbol("getInstalledPackages"), FunctionTemplate::New(InstalledPackages)->GetFunction());
}

NODE_MODULE(apt, Initialize)

Этот код теперь работает, однако теперь я перебираю список строк и делаю из них новые строки V8 в основном цикле событий. С таким же успехом я мог бы начать все это синхронно. Поскольку список пакетов может быть длиной около 30000 строк, я не хочу делать это в цикле событий javascript. Как я могу создать большой массив строк асинхронно?

2

Решение

Задача ещё не решена.

Другие решения


По вопросам рекламы [email protected]