“Iterating” throw promises does not let to generate different ids

三世轮回 提交于 2019-12-12 02:17:53

问题


Reading some amazing tutorials about promises, I've discovered that, if I need to interate throw some promises, I can't use forEach or some other "traditional" iteration mechanisms, I have to use Q library for node, I've to "iterate" using Q.all.

I've written a simple example in Nodejs Express in order to be sure I've understood 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 code simply is a promise with a console.log call, the same for Field.insert and Meta.insert

var Form = {
    insert: (param1,req) => {
        var deferred = Q.defer();
        console.log('Goes throw Form');
        deferred.resolve();
        return deferred.promise;
    }
}

The problem is that seems to iterate right but the dynamicly generated id does not change along the promises, this is the console output:

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

Any ideas about what is going wrong? Thanks!!


回答1:


the reason it is not working is because in first for loop, the req.id is set multiple times before other promises are started and and all of them end up using the last randomly generated value, change your code to:

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'));
})

you would notice that I am copying all the attributes of req to clone reqCopy for I am not sure what attributes of req are required by the subsequent methods, but at the same time, single req.id would not work thanks to the async nature of code



来源:https://stackoverflow.com/questions/37432906/iterating-throw-promises-does-not-let-to-generate-different-ids

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!