2017-02-27 39 views
2

考慮以下(人爲)例如:與藍鳥,茉莉未處理拒絕錯誤和一個異步函數

import Promise from 'bluebird'; 

const resolvedPromise =() => { 
    return Promise.resolve('Test'); 
}; 

const asyncFunc = async (asyncResource) => { 
    await resolvedPromise(); 
    await asyncResource.fetchItem(); 
}; 


describe('async/await',() => { 
    it('should throw an error', (done) => { 
     const mockAsyncResource = jasmine.createSpyObj('mockAsyncResource', ['fetchItem']); 

     const mockError = Promise.reject(new Error('HTTP 401 - Access Denied')); 

     mockAsyncResource.fetchItem.and.returnValue(mockError); 

     return asyncFunc(mockAsyncResource).catch(err => { 
      expect(err.message).toEqual('HTTP 401 - Access Denied'); 
      done(); 
     }); 
    }); 
}); 

我收到以下輸出:

1) async/await 
Unhandled rejection Error: HTTP 401 - Access Denied 
... (error stack trace) 

✔ should throw an error 

該規範通過,但藍鳥抱怨未處理的拒絕錯誤。

由於等待的阻塞性質,mockError報告它在第二個await有機會致電(並處理)mockError承諾之前未處理拒絕?

什麼是處理這種情況的最好方法是什麼?我發現了promise.suppressUnhandledRejections(),這是如此簡單嗎?

回答

2

我認爲這是由混合2種不同類型的承諾的問題。您正在使用藍鳥的Promise創建已解決/拒絕的模擬承諾,但await會返回原生Promise

如果你嘗試鉻控制檯下面,你將看到它的作品如你預期只使用本地時承諾:

let resolvedPromise =() => { 
    return Promise.resolve('Test'); 
}; 

let asyncFunc = async (asyncResource) => { 
    await resolvedPromise(); 
    await asyncResource.fetchItem(); 
}; 

let mockAsyncResource = {fetchItem:() => Promise.reject(new Error("foo"))}; 

asyncFunc(mockAsyncResource).catch((e) => console.log('handled')) 

如果你想堅持與創建藍鳥的承諾,你可能需要包裝與藍鳥的Promise.try您的異步功能,但我一直沒能對此進行測試:

let asyncFunc = async (asyncResource) => { 
    return Promise.try(async() => { 
     await resolvedPromise(); 
     await asyncResource.fetchItem(); 
    }); 
}; 
+0

啊,好趕上!我在我的代碼中的其他地方使用了藍鳥,並且很熟悉它的導入。沒有考慮承諾'等待'退貨的類型。 –

+0

果然切換到規格中的原生Promise解決了這個問題,所以我很高興將其標記爲答案。 另外...有趣的是,我繼續前進並進一步測試,Bluebird在原生Promise甚至返回之前發出未處理的拒絕錯誤。不確定這是否意味着它可能是一個時間問題,或只是像你所建議的Promise類型之間的不兼容。 –

+0

我想你總是可以通過玩超時來測試計時問題的想法,但我懷疑更多關於不兼容的問題,並且藍鳥的承諾會繼續等待返回的諾言。但是我無法確切地告訴你! –

相關問題