用 Q 迭代
Iterating with Q
我在 MongoDB 中有这个集合(为简洁起见,我省略了 _id
s):
test> db.entries.find();
{
"val": 1
}
{
"val": 2
}
{
"val": 3
}
{
"val": 4
}
{
"val": 5
}
我需要对每个文档执行一些我无法使用 db.update()
进行的处理。因此,简而言之,我需要做的是一次检索一个文档,在 Node 中处理它并将其保存回 Mongo.
我正在使用 Monk 库,并使用 Q 来获取 promises。这是我所做的 — 为简洁起见,我没有包含 processing/save 位:
var q = require('q');
var db = require('monk')('localhost/test');
var entries = db.get('entries');
var i = 1;
var total;
var f = function (entry) {
console.log('i = ' + i);
console.log(entry.val);
i++;
if (i <= total) {
var promise = entries.findOne({ val: i });
loop.then(function (p) {
return f(p);
});
return promise;
}
};
var loop = q.fcall(function () {
return entries.count({});
}).then(function (r) {
total = r;
return entries.findOne({ val: i });
}).then(f);
我希望打印出这段代码:
i = 1
1
i = 2
2
i = 3
3
i = 4
4
i = 5
5
但它实际打印出来:
i = 1
1
i = 2
2
i = 3
2
i = 4
2
i = 5
2
我做错了什么?
在您的代码中,循环是唯一的一个承诺。它只执行一次。它不是一个函数。
在f
里面,loop.then(f)
只要用promise的结果触发f
(已经执行过所以不会再执行)。
您实际上想要创建多个承诺。
您正在寻找的东西应该看起来像:
var q = require('q');
var db = require('monk')('localhost/test');
var entries = db.get('entries');
var i = 1;
var total;
var f = function (entry) {
console.log('i = ' + i);
console.log(entry.val);
i++;
if (i <= total) {
// I am not sure why you put entries.findOne here (looks like a mistake,
// its returned value isn't used) but if you really need it to be done
// before loop, then you must pipe it before loop
return entries.findOne({ val: i }).then(loop);
// do not pipe f again here, it is already appended at the end of loop
}
};
function loop(){
return q.fcall(function () {
return entries.count({});
}).then(function (r) {
total = r;
return entries.findOne({ val: i });
}).then(f);
}
loop();
我在 MongoDB 中有这个集合(为简洁起见,我省略了 _id
s):
test> db.entries.find();
{
"val": 1
}
{
"val": 2
}
{
"val": 3
}
{
"val": 4
}
{
"val": 5
}
我需要对每个文档执行一些我无法使用 db.update()
进行的处理。因此,简而言之,我需要做的是一次检索一个文档,在 Node 中处理它并将其保存回 Mongo.
我正在使用 Monk 库,并使用 Q 来获取 promises。这是我所做的 — 为简洁起见,我没有包含 processing/save 位:
var q = require('q');
var db = require('monk')('localhost/test');
var entries = db.get('entries');
var i = 1;
var total;
var f = function (entry) {
console.log('i = ' + i);
console.log(entry.val);
i++;
if (i <= total) {
var promise = entries.findOne({ val: i });
loop.then(function (p) {
return f(p);
});
return promise;
}
};
var loop = q.fcall(function () {
return entries.count({});
}).then(function (r) {
total = r;
return entries.findOne({ val: i });
}).then(f);
我希望打印出这段代码:
i = 1
1
i = 2
2
i = 3
3
i = 4
4
i = 5
5
但它实际打印出来:
i = 1
1
i = 2
2
i = 3
2
i = 4
2
i = 5
2
我做错了什么?
在您的代码中,循环是唯一的一个承诺。它只执行一次。它不是一个函数。
在f
里面,loop.then(f)
只要用promise的结果触发f
(已经执行过所以不会再执行)。
您实际上想要创建多个承诺。 您正在寻找的东西应该看起来像:
var q = require('q');
var db = require('monk')('localhost/test');
var entries = db.get('entries');
var i = 1;
var total;
var f = function (entry) {
console.log('i = ' + i);
console.log(entry.val);
i++;
if (i <= total) {
// I am not sure why you put entries.findOne here (looks like a mistake,
// its returned value isn't used) but if you really need it to be done
// before loop, then you must pipe it before loop
return entries.findOne({ val: i }).then(loop);
// do not pipe f again here, it is already appended at the end of loop
}
};
function loop(){
return q.fcall(function () {
return entries.count({});
}).then(function (r) {
total = r;
return entries.findOne({ val: i });
}).then(f);
}
loop();