获取UnhandledPromiseRejectionWarning尽管尽可能地拒绝拒绝

时间:2018-04-17 06:34:47

标签: javascript node.js promise

我知道SO上涉及UnhandledPromiseRejectionWarning的问题的现有答案,但找不到的似乎与我的案例充​​分匹配。基本上,我以为我知道如何处理承诺。但是这个案子让我疯了,所以我想在这里寻求一些支持:如何摆脱这种警告?

我正在NodeJS中实现一些可写流,其实现为_write()

_write( data, encoding, doneFn ) {
    Promise.race( [
        this.getSocket(),
        new Promise( ( resolve, reject ) => {
            setTimeout( reject, 1000, Object.assign( new Error( `timeout on trying to connect w/ ${this.address}` ), { code: "ECONNREFUSED" } ) );
        } ),
    ] )
        .then( socket => {
            if ( socket ) {
                return new Promise( ( resolve, reject ) => {
                    socket.once( "error", reject );
                    socket.write( data, encoding, () => {
                        socket.removeListener( "error", reject );

                        resolve();
                    } );
                } );
            }
        } )
        .then( doneFn )
        .catch( error => {
            const { address } = this;

            switch ( error.code ) {
                case "EPIPE" :
                case "ECONNRESET" :
                    Log( `lost connection w/ ${address.id}` );
                    break;

                case "ECONNREFUSED" :
                    Log( `failed to connect w/ ${address.id}` );
                    break;
            }

            console.log( "error is", error.message );
            doneFn( error );
        } );
}

当我测试此代码以便在超时时正确发出错误时,我会得到神秘的UnhandledPromiseRejectionWarning

error is timeout on trying to connect w/ /ip4/127.0.0.1/tcp/1
(node:5052) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: timeout on trying to connect w/ /ip4/127.0.0.1/tcp/1

由于_write()无法通过设计工作,我很确定这个警告是由于此处给出的代码所致。但我无法弄清楚如何摆脱警告。即使明确地附加catch-handler也没有压制它。

更新:代码已经过重构和重新测试。尽管如此仍会记录拒绝警告。我首先使用的是NodeJS 6.11,但这次是8.11。

2 个答案:

答案 0 :(得分:0)

坦率地说,你的代码非常混乱。在尝试调试上述问题之前,您最好重写这样的代码。

_write( data, encoding, doneFn ) {
    Promise.race( [
        this.getSocket(),
        /* This below code should better be handled within method this.getSocket so we won't need to use Promise.race */
        new Promise((resolve, reject) => {
            setTimeout( reject, 1000, Object.assign( new Error( `timeout on trying to connect w/ ${this.address}` ), { code: "ECONNREFUSED" } ) );
        }),
    ] )
        .then( socket => {
            return socket && new Promise( ( resolve, reject ) => {
                socket.once( "error", reject );
                socket.write( data, encoding, () => {
                    socket.removeListener( "error", reject );

                    resolve();
                } );
            } );
        } )
        .then(doneFn)
        .catch(error => {
            const { address } = this;

            switch ( error.code ) {
                case "EPIPE" :
                case "ECONNRESET" :
                    Log( `lost connection w/ ${address.id}` );
                    break;

                case "ECONNREFUSED" :
                    Log( `failed to connect w/ ${address.id}` );
                    break;
            }
            doneFn( error );
        });
}

答案 1 :(得分:0)

看起来流实施存在问题w / Promise.race()

我试图将代码细分为基本模式:

function someHandler( doneFn ) {
    const toBeResolvedLate = new Promise( ( resolve, reject ) => {
        setTimeout( resolve, 5000 );
    } );
    const toBeRejectedEarly = new Promise( ( resolve, reject ) => {
        setTimeout( reject, 1000, new Error( "timeout" ) );
    } );

    Promise.race( [
        toBeRejectedEarly,
        toBeResolvedLate,
    ] )
        .then( doneFn )
        .catch( error => {
            doneFn( error );
        } );
}


someHandler( ( ...args ) => {
    console.log( "directly:", args );
} );


const { Writable } = require( "stream" );

const stream = new Writable( {
    write: function( a, b, done ) {
        someHandler( ( ...args ) => {
            console.log( "in _write:", args );
            done( ...args );
        } );
    },
} );

stream.write( Buffer.from( "chunk" ) );

结果我得到了这个:

directly: [ Error: timeout
    at Promise (...\scratch_2.es6:6:30)
    at new Promise (<anonymous>)
    at someHandler (...\scratch_2.es6:5:29)
    at Object.<anonymous> (...\scratch_2.es6:20:2)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Function.Module.runMain (module.js:693:10) ]
in _write: [ Error: timeout
    at Promise (...\scratch_2.es6:6:30)
    at new Promise (<anonymous>)
    at someHandler (...\scratch_2.es6:5:29)
    at Writable.write [as _write] (...\scratch_2.es6:29:4)
    at doWrite (_stream_writable.js:397:12)
    at writeOrBuffer (_stream_writable.js:383:5)
    at Writable.write (_stream_writable.js:290:11)
    at Object.<anonymous> (...\scratch_2.es6:36:9)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10) ]
(node:3288) UnhandledPromiseRejectionWarning: Error: timeout
    at Promise (...\scratch_2.es6:6:30)
    at new Promise (<anonymous>)
    at someHandler (...\scratch_2.es6:5:29)
    at Writable.write [as _write] (...\scratch_2.es6:29:4)
    at doWrite (_stream_writable.js:397:12)
    at writeOrBuffer (_stream_writable.js:383:5)
    at Writable.write (_stream_writable.js:290:11)
    at Object.<anonymous> (...\scratch_2.es6:36:9)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
(node:3288) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:3288) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

如果我省略了尝试写入块的最后一行代码,那么第二个堆栈跟踪以及UnhandledPromiseRejectionWarning - 东西就会消失。