两年后,这个问题刚刚出现在我的 RSS 客户端...
自 2012 年 5 月以来,事情发生了一些变化,我们现在可能会选择以不同的方式解决这个问题。更具体地说,自从决定Array.prototype.reduce
在 ECMAScript5 中包含(和其他数组方法)以来,Javascript 社区已经变得“具有减少意识”。Array.prototype.reduce
一直(并且仍然)可以作为 polyfill 使用,但当时我们中的许多人都很少欣赏它。当然,那些走在曲线前面的人可能会反对这一点。
问题中提出的问题似乎是公式化的,规则如下:
- 数组中的对象作为第一个参数传递,
conn.collection(table).insert()
构建如下(其中N
对应于对象在数组中的索引):
- [ {}, ... ]
- [ {userId:userN._id}, ... ]
- [ {userId:userN._id, channelId:channelN._id}, ... ]
- 表名(按顺序)是 :
users
, channels
, articles
.
- 对应的对象属性是 :
user
, channel
, article
(即不带复数“s”的表名)。
Taoofcode的这篇文章中的一个通用模式,用于进行串行异步调用:
function workMyCollection(arr) {
return arr.reduce(function(promise, item) {
return promise.then(function(result) {
return doSomethingAsyncWithResult(item, result);
});
}, q());
}
通过非常轻松的适应,可以使用此模式来编排所需的顺序:
function cascadeInsert(tables, n) {
/*
/* tables: array of unpluralisd table names
/* n: number of users to insert.
/* returns promise of completion|error
*/
var ids = []; // this outer array is available to the inner functions (to be read and written to).
for(var i=0; i<n; i++) { ids.push({}); } //initialize the ids array with n plain objects.
return tables.reduce(function (promise, t) {
return promise.then(function (docs) {
for(var i=0; i<ids.length; i++) {
if(!docs[i]) throw (new Error(t + ": returned documents list does not match the request"));//or simply `continue;` to be error tolerant (if acceptable server-side).
ids[i][t+'Id'] = docs[i]._id; //progressively add properties to the `ids` objects
}
return insert(ids, t + 's');
});
}, Q());
}
最后,这是返回承诺的工作函数insert()
:
function insert(ids, t) {
/*
/* ids: array of plain objects with properties as defined by the rules
/* t: table name.
/* returns promise of docs
*/
var dfrd = Q.defer();
conn.collection(t).insert(ids, function(err, docs) {
(err) ? dfrd.reject(err) : dfrd.resolve(docs);
});
return dfrd.promise;
}
因此,您可以指定传递给cascadeInsert
的参数、实际表/属性名称和要插入的用户数。
cascadeInsert( ['user', 'channel', 'article'], 2 ).then(function () {
// you get here if everything was successful
}).catch(function (err) {
// you get here if anything failed
});
这很好用,因为问题中的表格都有常规复数形式(用户 => 用户,频道 => 频道)。如果其中任何一个是不规则的(例如刺激 => 刺激,孩子 => 孩子),那么我们需要重新考虑 - (并且可能实现查找哈希)。无论如何,适应将是相当微不足道的。