阅读关于承诺的some amazing tutorials,我发现,如果我需要互相投入一些承诺,我就无法使用每个或其他传统的#34;迭代机制,我必须使用Q库作为节点,我必须"迭代"使用Q.all
。
我在Nodejs Express中写了一个简单的例子,以确保我理解了承诺:
var form = [
{'name':'FORM_NAME_1.1',
'label2':'FORM_LABEL_1.2'
},
{'name':'FORM_NAME_2.1',
'label2':'FORM_LABEL_2.2'
}
];
var params = ['params1','params2'];
var meta = ['meta1','meta2'];
app.get('/', (req,res) => {
return Q.all([
form.map((currentValue,index,arr) => {
req.id = Math.random(); //Random ID to be used in the next promises
console.log(currentValue);
return Form.insert(currentValue,req);
}),
params.map((currentValue,index,arr) => {
console.log(req.id);
return Field.insert(currentValue,req.id);
}),
meta.map((currentValue,index,arr) => {
console.log(req.id);
return Meta.insert(currentValue,req.id);
})
])
.catch((err) => next(err))
.done(() => console.log('It\'s done'));
});
Form.insert
代码只是一个console.log
来电的承诺,同样适用于Field.insert
和Meta.insert
var Form = {
insert: (param1,req) => {
var deferred = Q.defer();
console.log('Goes throw Form');
deferred.resolve();
return deferred.promise;
}
}
问题是似乎迭代正确但动态生成的id
不会改变沿着承诺,这是控制台输出:
Listening at port 3000...
{ name: 'FORM_NAME_1.1', label2: 'FORM_LABEL_1.2' }
Goes throw Form
{ name: 'FORM_NAME_2.1', label2: 'FORM_LABEL_2.2' }
Goes throw Form
0.3757301066790548
Goes throw Field
0.3757301066790548
Goes throw Field
0.3757301066790548
Goes throw Meta
0.3757301066790548
Goes throw Meta
It's done
关于出了什么问题的任何想法?谢谢!
答案 0 :(得分:1)
它不起作用的原因是因为在第一个for循环中,req.id
在其他promises启动之前被设置了多次,并且所有这些都使用最后一个随机生成的值结束,将代码更改为:
app.get('/', (req,res) => {
let process = (currentValue,index,arr) => {
let reqCopy = {id: Math.random()}
for(let attr in req) // copy all the request attributes
if(attr && attr!='id')
reqCopy[attr] = req[attr]
return Q.all([
Form.insert(form[index],reqCopy),
Field.insert(params[index],reqCopy),
Meta.insert(meta[index],reqCopy)
])
}
return Q.all(form.map(process))
.catch(next)
.done(() => console.log('It\'s done'));
})
您会注意到我正在将req
的所有属性复制到克隆reqCopy
,因为我不确定后续方法需要req
的哪些属性,但同时时间,由于代码的异步特性,单req.id
将无效。