"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.insertMeta.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 将无法工作