【问题标题】:Promises stop working when adding a insertion query添加插入查询时,Promise 停止工作
【发布时间】:2016-05-26 17:32:51
【问题描述】:

询问关于 node 的 Q 库的承诺,mido 帮助我解决了执行承诺 in this thread 的问题。基本上,解决方案是(几乎)这段代码。

    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'];

    let process = (currentValue,index,arr) => {
        //let reqCopy = {id: Math.random()}
        let reqCopy = {};
        for(let attr in req)  // copy all the request attributes 
            //if(attr && attr!='id')
                reqCopy[attr] = req[attr]
        return Q.all([
            Form.insert(connection,req,form[index],reqCopy),
            Field.insert(connection,req,params[index],reqCopy),
            Meta.insert(connection,req,meta[index],reqCopy)
        ])
    }
    return Q.all(form.map(process))
    .catch((err) => console.log(err))
    .done(() => console.log('Done'));

但现在我需要在第一个承诺 (Form.insert) 中生成一个 id 并将其传递给其他人。使用 Node.js 的 mySql 库很容易获得插入行的 id。这是Form的承诺形式:

var Q = require('Q');

module.exports = {
    insert: (connection,req,dataToInsert,reqCopy) => {
        var deferred = Q.defer()
          , db       = 'DATABASE';

        console.log('Form.insert is executing with data: ' + JSON.stringify(dataToInsert));

    connection.query(`INSERT INTO ${db} SET ?`
        ,[dataToInsert]
        ,function(err, result) {
            if (err) deferred.reject(err);
            console.log('Result: ' + result.insertId);
            deferred.resolve(result.insertId); //Return id when data was inserted
        });

        return deferred.promise;
    }
}

但是现在,使用INSERT INTOquery,第一个承诺在流程结束时执行,再次失败:

//Promises are executed in the right order set in the .all array:
Form.insert is executing with data: {"name":"crf_NAME_1.1","label2":"FORM_LABEL_1.2"}
Field.insert is executing with data: "params1"
Meta.insert is executing with data: "meta1"
Form.insert is executing with data: {"name":"FORM_NAME_2.1","label2":"FORM_LABEL_2.2"}
Field.insert is executing with data: "params2"
Meta.insert is executing with data: "meta2"

//But Form.insert should generate the id before passing to the next promise.
C:\node\api\models\Form.js:17
            console.log('Result: ' + result.insertId); //IT FAILS, SHOULD BE EXECUTED BEFORE

我不明白为什么会发生这种情况,因为 Form.insert 被定义为一个承诺,并且在插入数据后设置了返回值(解析和拒绝),因此流应该等待它的解析。

谢谢!

【问题讨论】:

  • 您希望 Field.insert 和 Meta.insert 使用来自 Form.insert 的 Id?

标签: node.js promise q


【解决方案1】:

如果您想将第一个承诺中的 id 传递给其他人,您可以执行以下操作:

...
let process = (currentValue,index,arr) => {
  return Form.insert(connection,req,form[index]).then(id => Q.all([
    Field.insert(connection,req,params[index],id),
    Meta.insert(connection,req,meta[index],id)
  ]))
}
...

【讨论】:

    【解决方案2】:

    AFAIK,Q.all() 如果操作彼此独立,则很有用。

    如果存在 依赖项,则可以使用常规 Promise 链接:

    return Form .insert(connection,req,form[index],reqCopy)
                .then((insertId) => {
                  return Q.all([
                    Field.insert(connection, req, insertId, params[index], reqCopy), 
                    Meta .insert(connection, req, insertId, meta[index], reqCopy)
                  ])
                })
    

    这假设Field.insert()Meta.insert() 仍然相互独立;如果没有,您可以使用相同的技巧将数据从前者传递给后者。我添加了insertId 作为插入方法的额外参数作为示例。

    【讨论】:

      猜你喜欢
      • 2017-01-24
      • 2011-06-17
      • 2013-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-27
      • 1970-01-01
      • 2016-02-24
      相关资源
      最近更新 更多