Bluebird Promise 串行迭代,并解析为修改后的数组?
Bluebird Promise serial iteration, and resolve to modified array?
我有这个承诺,如果在数据库中找不到它,我会创建一个新的 Item
文档,然后将其存储在以前创建的 Collection
文档中..
Collection 文档是数组中的第一个字符串,数组中的任何后续索引都转换为一个或多个 Item 文档。
Promise.each "Resolves to the original array unmodified" 等 Promise.each
中的最后一个 return
正在渲染对象,但随后的 .then
生成原始数组。
这是承诺(为了便于阅读而缩写):
globalVar = true;
collectionId = "";
var itemSeries = Promise.each(items, function(element) {
if (globalVar == true) {
return Models.Collection.findOneAsync({
"name": element
})
.then(function(collection) {
// promise chain similar to the following else..
// set the collectionId var to an _id
});
} else {
return Models.Items.findOneAsync({
"name": element
})
.then(function(item) {
if (item == null) {
return Models.Labels.findOneAsync({
"title": element
})
.then(function(label) {
var newItem = new Models.Items({
name: element,
label: label._id
});
return newItem.saveAsync();
}).then(function() {
return Models.Items.findOneAsync({
"name": element
});
}).then(function(item) {
item.collection = collectionId;
return item.saveAsync();
}).then(function() {
return Models.Items.findOneAsync({
"name": element
});
}).then(function(item) {
allItems.push(item);
console.log("allItems: [ ");
console.log(allItems);
return allItems;
});
}
});
}
}).then(function(allItems) {
console.log("allItems: [ ");
console.log(allItems);
return allItems;
});
这是 Promise.each 中的最后一个 console.log
:
allItems: [
[ { _id: 54eec5f2b9fb280000286d52,
name: 'one',
label: 54eec5f2b9fb280000286d51,
collection: 54eec5f2b9fb280000286d50,
__v: 0 },
{ _id: 54eec5f2b9fb280000286d54,
name: 'two',
label: 54eec5f2b9fb280000286d53,
collection: 54eec5f2b9fb280000286d50,
__v: 0 } ]
然后在随后的 .then(function(allItems) {
这是最后一个 console.log
:
allItems: [
[ 'collectionName', 'one', 'two' ]
此外,= Promise.each
稍后在 Promise.join?
中呈现 undefined
的变量 itemSeries
.each
函数不会改变通过链的值:
我简化了你的代码,作为我假设的输入:
var items = ['one','two'];
对于您的代码:
Promise.each(items, function(element) {
return element+'.';
//return Promise.resolve(element+'.');
})
.then(function(allItems) {
console.dir(allItems);
});
结果仍将是 ['one','two']
,因为这是数组 items
的解析值。 each 中的返回值不影响传递给链式 then
.
的值的内容
另一方面,.map
函数会产生这样的效果:
Promise.map(items, function(element) {
return element+'.';
//return Promise.resolve(element+'.');
})
.then(function(allItems) {
console.dir(allItems);
});
此处return
value 值将用于创建一个新数组,然后将其传递给then
。这里的结果是 ['one.','two.']
.
你代码中出现的两个allItems
是不同的对象。
编辑
对于带有映射的串行迭代,我会编写一个这样的辅助函数:
function mapSeries(things, fn) {
var results = [];
return Promise.each(things, function(value, index, length) {
var ret = fn(value, index, length);
results.push(ret);
return ret;
}).thenReturn(results).all();
}
Bluebird 现在原生实现了 mapSeries
,参见 http://bluebirdjs.com/docs/api/promise.mapseries.html
看起来 Promise.each
仍然是 returns 不幸的是 v3.x.x 中的原始数组。
我有这个承诺,如果在数据库中找不到它,我会创建一个新的 Item
文档,然后将其存储在以前创建的 Collection
文档中..
Collection 文档是数组中的第一个字符串,数组中的任何后续索引都转换为一个或多个 Item 文档。
Promise.each "Resolves to the original array unmodified" 等 Promise.each
中的最后一个 return
正在渲染对象,但随后的 .then
生成原始数组。
这是承诺(为了便于阅读而缩写):
globalVar = true;
collectionId = "";
var itemSeries = Promise.each(items, function(element) {
if (globalVar == true) {
return Models.Collection.findOneAsync({
"name": element
})
.then(function(collection) {
// promise chain similar to the following else..
// set the collectionId var to an _id
});
} else {
return Models.Items.findOneAsync({
"name": element
})
.then(function(item) {
if (item == null) {
return Models.Labels.findOneAsync({
"title": element
})
.then(function(label) {
var newItem = new Models.Items({
name: element,
label: label._id
});
return newItem.saveAsync();
}).then(function() {
return Models.Items.findOneAsync({
"name": element
});
}).then(function(item) {
item.collection = collectionId;
return item.saveAsync();
}).then(function() {
return Models.Items.findOneAsync({
"name": element
});
}).then(function(item) {
allItems.push(item);
console.log("allItems: [ ");
console.log(allItems);
return allItems;
});
}
});
}
}).then(function(allItems) {
console.log("allItems: [ ");
console.log(allItems);
return allItems;
});
这是 Promise.each 中的最后一个 console.log
:
allItems: [
[ { _id: 54eec5f2b9fb280000286d52,
name: 'one',
label: 54eec5f2b9fb280000286d51,
collection: 54eec5f2b9fb280000286d50,
__v: 0 },
{ _id: 54eec5f2b9fb280000286d54,
name: 'two',
label: 54eec5f2b9fb280000286d53,
collection: 54eec5f2b9fb280000286d50,
__v: 0 } ]
然后在随后的 .then(function(allItems) {
这是最后一个 console.log
:
allItems: [
[ 'collectionName', 'one', 'two' ]
此外,= Promise.each
稍后在 Promise.join?
undefined
的变量 itemSeries
.each
函数不会改变通过链的值:
我简化了你的代码,作为我假设的输入:
var items = ['one','two'];
对于您的代码:
Promise.each(items, function(element) {
return element+'.';
//return Promise.resolve(element+'.');
})
.then(function(allItems) {
console.dir(allItems);
});
结果仍将是 ['one','two']
,因为这是数组 items
的解析值。 each 中的返回值不影响传递给链式 then
.
另一方面,.map
函数会产生这样的效果:
Promise.map(items, function(element) {
return element+'.';
//return Promise.resolve(element+'.');
})
.then(function(allItems) {
console.dir(allItems);
});
此处return
value 值将用于创建一个新数组,然后将其传递给then
。这里的结果是 ['one.','two.']
.
你代码中出现的两个allItems
是不同的对象。
编辑 对于带有映射的串行迭代,我会编写一个这样的辅助函数:
function mapSeries(things, fn) {
var results = [];
return Promise.each(things, function(value, index, length) {
var ret = fn(value, index, length);
results.push(ret);
return ret;
}).thenReturn(results).all();
}
Bluebird 现在原生实现了 mapSeries
,参见 http://bluebirdjs.com/docs/api/promise.mapseries.html
看起来 Promise.each
仍然是 returns 不幸的是 v3.x.x 中的原始数组。