"Iterating" throw promises 不允许生成不同的 id
"Iterating" throw promises does not let to generate different ids
阅读 some amazing tutorials 关于 promises 的内容,我发现,如果我需要交互抛出一些 promises,我不能使用 forEach 或其他一些 "traditional" 迭代机制,我必须 为节点使用 Q 库,我必须 "iterate" 使用 Q.all
。
我已经在 Nodejs Express 中编写了一个简单示例,以确保我理解了 promises:
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
有什么问题吗?谢谢!!
它不起作用的原因是因为在第一个 for 循环中,req.id
在其他承诺开始之前被多次设置,并且所有承诺最终都使用最后一个随机生成的值,更改您的代码至:
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
将无法工作
阅读 some amazing tutorials 关于 promises 的内容,我发现,如果我需要交互抛出一些 promises,我不能使用 forEach 或其他一些 "traditional" 迭代机制,我必须 为节点使用 Q 库,我必须 "iterate" 使用 Q.all
。
我已经在 Nodejs Express 中编写了一个简单示例,以确保我理解了 promises:
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
有什么问题吗?谢谢!!
它不起作用的原因是因为在第一个 for 循环中,req.id
在其他承诺开始之前被多次设置,并且所有承诺最终都使用最后一个随机生成的值,更改您的代码至:
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
将无法工作