手动蓝鸟承诺中的resolve()

时间:2017-03-21 16:43:41

标签: javascript node.js bluebird

超级基本问题:我是nodeJS和Promises的新手,对我是否正确使用resolve()感到好奇。



   _queryHelper( query, fields )
    {
        return new Promise( ( resolve, reject ) => {
            connector.query( query, fields, ( error, results ) => {
                if( error )
                {
                    connector.rollback( () => {
                        reject( error );
                    } );
                }
                if( results )
                {
                    return resolve( results );
                }
                resolve();
            });
        });
    };
   
// later on doing something like:
this._queryHelper( 'SELECT * FROM secretTable WHERE `generatedURL` = ?', stringIn )
.then( ( resultsIn ) => {
    if( !resultsIn || resultsIn.length === 0 ) {
        // do somthing
    }
    else {
       // do something else
    }
});




所以直接问题是,当我使用.then()时,我是否正确地从原始的promise查询中冒出结果?基本上我正在努力确定我的原始'返回的确切位置(结果)'实际上我可以访问前面提到的结果'

编辑:从_queryHelper调用resolve(结果)时,我是否正确理解'结果'被传递给我的.then作为' resultsIn'?

2 个答案:

答案 0 :(得分:0)

如果您只是询问您的代码是否有效,那么您的结果值应该会在您没有错误时显示在您希望的位置。

resolve(results)会让results显示在您的.then()处理程序中。

我发现您的代码存在三个主要问题:

  1. 您的错误处理无法正常工作。
  2. 未定义results时出现逻辑问题。
  3. 您错过了.catch()来处理错误。
  4. 如果没有结果,则.then()处理程序中存在逻辑问题,因为:

    if (results.length) 
    
    resultsundefined时,

    会抛出。为安全起见,您可以将if更改为此:

    if (!results || results.length === 0)
    

    您还应该解决发生错误时会遇到的问题,以免在出现错误时调用resolve()。我建议改为:

       _queryHelper(query, fields) {
           return new Promise((resolve, reject) => {
               connector.query(query, fields, (error, results) => {
                   if (error) {
                       connector.rollback(() => {
                           reject(error);
                       });
                   } else {
                       resolve(results);
                   }
               });
           });
       };
    
       // later on doing something like:
       this._queryHelper('SELECT * FROM secretTable WHERE `generatedURL` = ?', stringIn).then((resultsIn) => {
           if (!resultsIn || resultsIn.length === 0) {
               // do somthing
           } else {
               // do something else
           }
       }).catch(err => {
           // handle errors here
       });
    

答案 1 :(得分:0)

  

我是否理解results已作为.then传递给resultsIn回调?

是的,这可以按预期工作。

但是,您的代码无效,因为即使出现错误,您也始终会调用resolve()。这是一个问题,特别是因为您在回滚连接器后尝试reject()承诺 - 但到那时承诺已经解决。您需要else

return new Promise((resolve, reject) => {
    connector.query(query, fields, (error, results) => {
        if (error) {
            connector.rollback(() => {
                reject(error);
            });
        } else { // <===
            if (results)
                return resolve(results);
            resolve();
        }
    });
});

(或开始回滚后的return)。而且你根本不需要进行if (results)测试 - 无论如何,当它是假的时候你会用undefined来解决。更好的做法

return new Promise((resolve, reject) => {
    connector.query(query, fields, (error, results) => {
        if (error) {
            connector.rollback(() => {
                reject(error);
            });
        } else {
            resolve(results);
        }
    });
});

也就是说,使用Bluebird时,如果有automatic promisification,则永远不需要使用Promise构造函数:

const queryConnector = Promise.promisify(connector.query, {context: connector});
const rollbackConnector = Promise.promisify(connector.rollback, {context: connector});

function _queryHelper(query, fields) {
    return queryConnector(query, fields).catch(error =>
        rollbackConnector().throw(error)
    );
}

甚至更简单:

Promise.promisifyAll(connector);

function _queryHelper(query, fields) {
    return connector.queryAsync(query, fields).catch(error => {
        return connector.rollbackAsync().throw(error);
    });
}