2017-10-16 2 views
0

나는 이전 문제는 여기 질문 : Retaining Data across multiple promise chains노드 처리되지 않은 약속 문제

내가 T.J.를 사용하여 종료 Crowder가 내 기본 코드에 대한 대답을하고 많은 변화를 일으켰습니다. 그러나 나는 극복 할 수없는 노드에서 이상한 것을 발견했습니다. 나는 그가 제공 한 기본 코드로 되돌아 갔고 문제는 거기에있는 것처럼 보인다. 나는 이것을 실행할 때

"use strict"; 

// For tracking our status 
class Status { 
    constructor(total = 0, count = 0) { 
     this.id = ++Status.id; 
     this.total = total; 
     this.count = count; 
    } 
    addCall() { 
     ++this.total; 
     return this; 
    } 
    addProgress() { 
     ++this.count; 
     return this; 
    } 
    toString() { 
     return `[S${this.id}]: Total: ${this.total}, Count: ${this.count}`; 
    } 
} 
Status.id = 0; 

// The promise subclass 
class RepoPromise extends Promise { 
    constructor(executor) { 
     super(executor); 
     this.s = new Status(); 
    } 
    // Utility method to wrap `then`/`catch` callbacks so we hook into when they're called 
    _wrapCallbacks(...callbacks) { 
     return callbacks.filter(c => c).map(c => value => this._handleCallback(c, value)); 
    } 
    // Utility method for when the callback should be called: We track that we've seen 
    // the call then execute the callback 
    _handleCallback(callback, value) { 
     this.s.addProgress(); 
     console.log("Progress: " + this.s); 
     return callback(value); 
    } 
    // Standard `then`, but overridden so we track what's going on, including copying 
    // our status object to the new promise before returning it 
    then(onResolved, onRejected) { 
     this.s.addCall(); 
     console.log("Added: " + this.s); 
     const newPromise = super.then(...this._wrapCallbacks(onResolved, onRejected)); 
     newPromise.s = this.s; 
     return newPromise; 
    } 
    // Standard `catch`, doing the same things as `then` 
    catch(onRejected) { 
     this.s.addCall(); 
     console.log("Added: " + this.s); 
     const newPromise = super.catch(...this._wrapCallbacks(onRejected)); 
     newPromise.s = this.s; 
     return newPromise; 
    } 
} 

// Create a promise we'll resolve after a random timeout 
function delayedGratification() { 
    return new Promise(resolve => { 
     setTimeout(_ => { 
      resolve(); 
     }, Math.random() * 1000); 
    }); 
} 

// Run! Note we follow both kinds of paths: Chain and diverge: 
const rp = RepoPromise.resolve('Test'); 
rp.then(function(scope) { 
    return new Promise((resolve, reject) => { 
     console.log(' Rejected') 
     reject(scope) 
    }) 
}) 
.catch(e => {console.log('Never Makes it')}) 

: 여기

은 예입니다 node test.js 나는 다음과 같은 출력을 얻을

Added: [S1]: Total: 1, Count: 0 
Added: [S1]: Total: 2, Count: 0 
Added: [S1]: Total: 3, Count: 0 
Progress: [S1]: Total: 3, Count: 1 
    Rejected 
(node:29364) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Test 
(node:29364) [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. 

주의 "never makes it"에 대한 콘솔 로그는 것을, 또한 현재주의하지, I 이미 catch이 두 번 실행되는 문제를 수정 했으므로 then(null, function(){})에 대한 간단한 구문 설탕이므로 무시해도됩니다.

내가 예상 한 것처럼 캐치가 작동하지 않는 이유는 무엇입니까? 정상적인 약속으로이 작업을 수행 할 때 아래와 같은 문제는 없습니다. 따라서 _wrapCallbacks이 문제를 일으킨다는 사실을 알고 있습니다. 이유 또는 해결 방법을 모르겠습니다.

const rp = Promise.resolve('Test'); 
rp.then(function(scope) { 
    return new Promise((resolve, reject) => { 
     console.log(' Rejected') 
     reject(scope) 
    }) 
}) 
.catch(e => {console.log('Makes it')}) 

답변

1

catch 약속 이행이 작동하지 않습니다. 네이티브 catchreturn this.then(null, callback)으로 구현됩니다. super.catch을 호출하면 then 구현로 돌아갑니다.

그리고 then 구현에는 중대한 오류가 있습니다. 기능 전에 null 인수를 얻는 것을 좋아하지 않습니다. 당신이이 일을 할 때 위의 호출에 발생하는 관찰 :

_wrapCallbacks(...callbacks) { 
    return callbacks.filter(c => c).map(…); 
//     ^^^^^^^^^^^^^^^ 
} 
then(onResolved, onRejected) { 
    … 
    const newPromise = super.then(...this._wrapCallbacks(onResolved, onRejected)); 
    … 
} 

단순히 인수의 배열에서 null를 제거하고 대신 onfulfilled으로 onrejected 콜백을 통과 겠죠. 대신 매핑 기능에 원을 filter을 삭제하고 사용할 수 있습니다 :

_wrapCallbacks(...callbacks) { 
    return callbacks.map(c => typeof c == "function" 
     ? value => this._handleCallback(c, value) 
     : c); 
} 

또한 그냥 무시 catch을 놓을 수 있습니다.

+0

예 이미 오버라이드 된 캐치를 놓았습니다. 감사합니다. 나는 왜 그가 필터를 사용했는지에 대해 혼란스러워했지만 지금은 알 수 있습니다. 이것은 정확하게 나의 문제점이었다, 나는 그것이 그 기능을 가진 무언가임을 알았다. 필터/맵을 다시 배워야한다고 가정합니다. 감사! – Krum110487

+0

Tbh, 나는'filter' /'map'을 전혀 사용하지 않았을 것이고, 단지'super.then (this._wrapCallback (onFulfilled), this._wrapCallback (onRejected));이라고 불렀다.' – Bergi

+0

동의했다. 필터 /지도의 근본적인 오해가 있습니다. 거의 사용하지 않기 때문에 null이 제거되었음을 알면 나에게 무슨 일이 벌어지고 있는지 이해할 수있었습니다. – Krum110487

관련 문제