javascript - 解决后如何停止 promise 链?

标签 javascript node.js promise

我想在通过某些条件解决后停止 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)。

当我尝试这段代码时,即使没有要更新的数据,第二个 then(updating db) 总是发生!

我读了this post ,但没有奏效。为什么当我调用“return resolve();”时 promise 链没有停止?以及如何正确停止它?我真的很喜欢使用 Promises,但有时,这种事情让我发疯。能帮我解决这个问题将不胜感激。谢谢!

附言无论如何,我正在使用 Node v6.2.2。

最佳答案

Why the promise chain wasn't stopped when I called "return resolve();"?

您已经从当前的 then 回调中返回并履行了外部 promise 。但这并没有“停止”任何事情,然后 then 链仍然会通过使用回调的返回值进行解析来继续。

And how to I stop it properly?

您需要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(); // ???
            });
        });
    }
}

关于javascript - 解决后如何停止 promise 链?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39955607/

相关文章:

javascript - 字符串值在被调用函数内变为 null

javascript - 将 bluebird Promise 添加到 NodeJS 模块,然后函数未定义

javascript - JQM 1.4.2 从ajax添加模板到弹出窗口不渲染

javascript - 错误: StaticInjectorError(AppModule)[PaginationComponent -> PaginationConfig]

android - 'node' 不被识别为 jenkins 的内部或外部命令错误

node.js - 如何在 Pug 模板文件中使用 i18n 变量?

javascript - Bluebird promisifyAll 在普通情况下不起作用

javascript - 如何在 VSCode 中为 Javascript AMD 模块启用 Intellisense

javascript - 如何在 React 应用程序中实现谷歌地图搜索框

ruby-on-rails - 从 Rail Active 调用 Socket.io :Record callback or observer