2016-12-04 90 views
1

我已經建立了一個功能,它通過Generator迭代同時包含同步代碼和Promises接收`UnhandledPromiseRejectionWarning`即使拒絕承諾的處理

module.exports = { 


    isPromise (value) { 
      return typeof value === 'object' && value !== null && 'then' in value; 
     }, 

    runGen (generatorFunc, startValue) { 

      let that = this, 
       i = 0; 

      function *iterator(resolve, reject) { 

       let runGeneratorFunc = generatorFunc(startValue), 
        yieldedOut = {done: false}, 
        yieldIn; 

       while (!yieldedOut.done) { 
        console.log(i++, 'Ready for next iteration'); 
        if (that.isPromise(yieldedOut.value)) { 
         console.log(i++, 'Pass promise to KeepIterating'); 
         yieldIn = yield yieldedOut.value; 
         console.log(i++, 'Received value from promise'); 

         if(yieldIn instanceof Error){ 
          console.log(i++, 'Value was instance of Error'); 
          try { 
           yieldedOut = runGeneratorFunc.throw(yieldIn) 
          } 
          catch(err){ 
           console.log(i++, 'Throw Error'); 
           throw(yieldIn); 
          } 
         } else { 
          yieldedOut = runGeneratorFunc.next(yieldIn); 
         } 
        } else { 
         try { 
          yieldIn = yieldedOut.value; 
          yieldedOut = runGeneratorFunc.next(yieldIn); 
         } 
         catch(err) { 
          runGeneratorFunc.throw(err); 
          reject(err); 
         } 
        } 
       } 
       resolve(yieldedOut.value); 
      } 

      return new Promise(function (resolve, reject) { 
       var runIterator = iterator(resolve, reject); 
       (function keepIterating(yieldIn) { 
        let yieldedOutPromise = runIterator.next(yieldIn); 

        if (!yieldedOutPromise.done) { 

         yieldedOutPromise.value.then(function (fulfilledValue) { 
          console.log('never gets here'); 
          keepIterating(fulfilledValue); 
         }); 

         yieldedOutPromise.value.catch(function (err) { 
          console.log(i++, 'Rejected promise catched'); 
          if (err instanceof Error) { 
           try { 
            console.log(i++, 'Rejected promise is instance of Error'); 
            let yieldedOut = runIterator.next(err); 
            keepIterating(yieldedOut); 
           } 
           catch (err) { 
            console.log(i++, 'Error propagated back out'); 
            yieldedOutPromise.value.catch(() => {}) 
            reject(err); 
           } 
          } else { 
           try { 
            let yieldedOut = runIterator.next(new Error(err)); 
            keepIterating(yieldedOut); 
           } 
           catch (err) { 
            reject(err); 
           } 
          } 
         }) 
        } 
       })(); 
      }); 
     } 
    } 

現在,當我導入和使用此代碼運行:

const md = require('./module'); 

function* dummy() { 
    yield Promise.reject(new Error('error1')); 
} 

md.runGen(dummy) 
.catch(err => { 
    console.log(9, 'Finished!'); 
}) 

我得到這個記錄到控制檯:

0 'Ready for next iteration' 
1 'Ready for next iteration' 
2 'Promise yielded out' 
3 'Rejected promise handled' 
4 'Rejected promise instance of Error' 
5 'Ready to handle promise value' 
6 'Value was instance of Error' 
7 'Throw Error' 
8 'Error propagated back out' 
9 'Finished!' 
(node:9904) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: error1 
(node:9904) 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的警告外,這一切均如預期。我很困惑,爲什麼我收到這個警告,因爲在我看來,被拒絕的Promise被處理了

我在忽略什麼?

+0

是否有任何語法錯誤? – guest271314

+0

否輸出完全如上所示。沒有什麼被遺漏 – rabbitco

+1

你真的不應該自己寫這些功能。使用一個提供它的庫(例如'Bluebird.coroutine')或立即使用'async' /'await'語法(使用合適的轉譯器)。 – Bergi

回答

2

我忽略了什麼?

您的yieldedOutPromise.value.then呼叫正在創建一個新的承諾,如果yieldedOutPromise.value拒絕,那麼它也會被拒絕。無關緊要,您通過yieldedOutPromise.value上的.catch來處理錯誤,但仍然有被拒絕的承諾,並且會被報告。

你基本上是分裂你的承諾鏈,導致每一端都需要一個錯誤處理程序。但是,你不應該分裂任何東西。取而代之的是

promise.then(onSuccess); 
promise.catch(onError); 

反模式,你應該使用

promise.then(onSuccess, onError).… 

哦,當你在它,avoid the Promise constructor antipattern。只要做

module.exports = function runGen (generatorFunc, startValue) { 
    return Promise.resolve(startValue).then(generatorFunc).then(generator => { 
     return keepIterating({done: false, value: undefined}); 
     function keepIterating({done, value}) { 
      if (done) return value; 
      return Promise.resolve(value).then(fulfilledValue => 
       generator.next(fulfilledValue) 
      , err => 
       generator.throw(err) 
      ).then(keepIterating); 
     } 
    }); 
}; 
+0

您提出的解決方案不會返回預期的結果。 – guest271314

+0

@ guest271314你是什麼意思?什麼是「預期結果」,OP的輸出日誌是什麼?它是什麼讓你回來? – Bergi

+0

你的方法沒有達到'console.log('永遠不會到達');' – guest271314

相關問題