解决后如何停止承诺链?

时间:2016-10-10 09:49:57

标签: javascript node.js promise

我希望在通过某些条件解决后停止承诺链。下面的代码可能有助于理解我在说什么。

function update(id, data) {
    return new Promise((resolve, reject) => {
        let conn;

        pool.get()
        .then((db) => {
            conn = db;

            if(Object.keys(data).length === 0) {
                return resolve({ updated: 0 });
            }
            else {
                return generateHash(data.password);
            }
        })
        .then((hash) => {
            conn.query("UPDATE ... ", (err, queryResult) => {
                if(err) {
                    throw err;
                }

                resolve({ updated: queryResult.affectedRows });
            });
        })
        .catch((err) => { ... })
    });
}

请注意,pool.get()是promise包装的API,用于从我创建的MySQL模块获取连接池。

我要做的是更新用户数据。为了节省服务器资源,如果没有要更新的数据,我就避免更新(Object.keys(data).length === 0)。

当我尝试使用此代码时,即使没有要更新的数据,也会发生第二次(更新数据库)!

我看了this post,但没有奏效。当我调用“return resolve();”时为什么没有停止承诺链?我该如何正确地阻止它?我真的很喜欢使用Promises,但有时候,这种事情会让我发疯。非常感谢帮助我解决这个问题。谢谢!

P.S。无论如何,我正在使用节点v6.2.2。

2 个答案:

答案 0 :(得分:5)

  

当我打电话给#34;返回resolve();"?

时,为什么承诺链没有停止?

您已从当前then回调中退回并履行了外部承诺。但那并没有停止"任何事情,然后then链仍然会继续解析回调的返回值。

  

如何正确阻止它?

您需要put the then call inside the if才能适用条件:

pool.get()
.then((db) => {
    …
    if (Object.keys(data).length === 0) {
        …({ updated: 0 });
    } else {
        return generateHash(data.password)
        .then((hash) => {
            conn.query("UPDATE ... ", (err, queryResult) => {
                …
            });
        })
    }
})
.catch((err) => { ... })

无论如何,你应该避免使用Promise constructor antipattern!您应该只promisify query方法:

function query(conn, cmd) {
    return new Promise((resolve, reject) => {
        conn.query(cmd, (err, queryResult) => {
            if (err) reject(err); // Don't throw!
            else resolve(queryResult);
        });
    });
}

然后使用:

function update(id, data) {
    return pool.get()
    .then(conn => {
        if (Object.keys(data).length === 0) {
            conn.close(); // ???
            return { updated: 0 };
        } else {
            return generateHash(data.password)
            .then(hash => {
                return query(conn, "UPDATE ... ")
            }).then(queryResult => {
                conn.close(); // ???
                return { updated: queryResult.affectedRows };
            }, err => {
                …
                conn.close(); // ???
            });
        }
    });
}

请注意,如果您事先知道不会进行查询,那么从池中获取连接可能没有意义,因此您可能应该将if置于顶层:

function update(id, data) {
   if (Object.keys(data).length === 0) {
       return Promise.resolve({ updated: 0 });
    } else {
       return pool.get()
       .then(conn => {
            return generateHash(data.password)
            .then(hash => {
                return query(conn, "UPDATE ... ")
            }).then(queryResult => {
                conn.close(); // ???
                return { updated: queryResult.affectedRows };
            }, err => {
                …
                conn.close(); // ???
            });
        });
    }
}

答案 1 :(得分:0)

使用if语句这是一个很好的情况:

function update(id, data) {
    if (Object.keys(data).length === 0) {
        return Promise.resolve({ updated: 0 }); 
    }

    let conn;

    return pool.get()
        .then((db) => {
            conn = db;

            return generateHash(data.password);
        })
        .then((hash) => {
            return new Promise(function (resolve, reject) {
                conn.query("UPDATE ... ", (err, queryResult) => {
                    if(err) {
                        reject(err);
                    }

                    resolve({ updated: queryResult.affectedRows });
                });
            });
        })
        .catch((err) => { ... })
}