2 年後、私の RSS クライアントにこの質問が表示されました...
2012 年 5 月以降、事態はいくぶん進展しており、現在は別の方法でこの問題を解決することを選択する可能性があります。Array.prototype.reduce
より具体的には、Javascript コミュニティは、ECMAScript5 に (および他の Array メソッドを)含めることを決定して以来、"reduce-aware" になりました。Array.prototype.reduce
ポリフィルとして常に (そして今も) 利用可能でしたが、当時はほとんど評価されませんでした。もちろん、時代を先取りしていた人たちは、この点について異議を唱えるかもしれません。
質問で提起された問題は、次のようなルールで定型化されているようです。
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());
}
最後に、Promise を返すワーカー関数は次の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
});
質問のテーブルにはすべて通常の複数形 (ユーザー => ユーザー、チャネル => チャネル) があるため、これはうまく機能します。それらのいずれかが不規則である場合 (例:刺激 => 刺激、子 => 子供)、再考する必要があります - (そしておそらくルックアップ ハッシュを実装します)。いずれにせよ、適応はかなり簡単です。