2

我有兩個函數可以處理Facebook登錄/註銷,前兩個函數都是用promise寫的。我想用async/await來重寫這些。用異步/等待重寫承諾,尋求澄清

原代碼與承諾:

export function login() { 
    return new Promise<facebookSdk.IAuthResponse>((resolve, reject) => { 
    FB.login((response) => { 
     if (response.authResponse) { 
     resolve(response) 
     } else { 
     reject(errors.facebookLoginError) 
     } 
    }) 
    }) 
} 

export function logout() { 
    return new Promise<facebookSdk.IAuthResponse>((resolve) => { 
    FB.logout((response) => { 
     resolve(response) 
    }) 
    }) 
} 

以下是我寫了他們使用async/await

function promiseFacebookLogin(): Promise<facebookSdk.IAuthResponse | Error> { 
    return new Promise<facebookSdk.IAuthResponse>((resolve, reject) => { 
    FB.login((response) => { 
     if (response.authResponse) { 
     resolve(response) 
     } else { 
     reject(errors.facebookLoginError) 
     } 
    }) 
    }) 
} 

export async function login(): Promise<facebookSdk.IAuthResponse | Error> { 
    try { 
    return await promiseFacebookLogin() 
    } catch (err) { 
    throw err 
    } 
} 

export async function logout(): Promise<facebookSdk.IAuthResponse | void> { 
    try { 
    return await FB.logout((response) => { 
     return response 
    }) 
    } catch (err) { 
    throw err 
    } 
} 

生成的代碼按預期工作,但有件事情我想澄清一下。正如你所看到的,我可以擺脫logout函數的全部promise語法。但是,當涉及到login函數時,我無法這樣做。我必須分開承諾,等待結果。據我研究,這似乎是回調函數的常見做法。

有人可以闡明爲什麼在login函數中不能完全擺脫Promise語法?

+0

難道你沒有寫你的'登錄'方法[像這樣](https://jsfiddle.net/uuzoufzd/)來消除承諾?我不確定這是否有效。 – Saravana

+0

這是FB.login的簽名:'login(callback:(response:IAuthResponse)=> void):void' 我不能在沒有回調的情況下調用它。 – cinnaroll45

+0

想'FB.login'會通過查看'FB.logout'返回一個承諾。如果'FB.logout'沒有返回promise,你怎麼能從'logout'方法返回任何東西?它不會總是返回'空白'嗎? – Saravana

回答

2

你不需要包裹FB.logout功能在一個無極包裝的原因是因爲你不使用的FB.logout,你基本上是「發射和忘記」解析值。你可以寫同樣的方法,無需像下面有同樣的效果:

export function logout(): void { 
    try { 
    FB.logout((response) => { 
     // no-op 
    }) 
    } catch (err) { 
    throw err 
    } 
} 

而且因爲你需要FB.login解決的價值,你必須將它包裝在一個Promiseasync/await使用它。

2

我們使用關鍵字async來調用返回Promise實例的函數。這些功能可以在其他功能的主體中使用。

還有就是轉向回調風格的API,一個共同的模式答應爲基礎的:

function fbLogin(..., cb) { ... } 

async function genFbLogin(...args): Promise<*> { 
    return new Promise((resolve, reject) => { 
    fbLogin(...args, (error, result) => { 
     if (error) { 
     reject(error);   
     } else { 
     resolve(result); 
     } 
    }); 
    }); 
} 

正如你可以看到login從你的例子已經是這種形式。它返回Promise,因此您可以在其聲明之前放置async關鍵字。與logout相同。這些已經是基於Promise的,而不是基於回調的。使用logout功能的正確方式是那麼的情況如下:

async function myLogoutHandler() { 
    try { 
    const response = await logout(); 
    console.log(response); // do sth with the result  
    } catch (e) { 
    console.log('error', e); 
    } 
} 

注意try-catch塊。將異步函數的主體封裝在這裏以捕獲等待承諾時可能拋出的任何錯誤是非常重要的。

+0

如果我錯了,請糾正我;你的'fbLogin'的例子在相同的代碼塊中返回promise,而我的只是在另一個函數中包裝了這個promise。他們都以同樣的方式工作。我的問題是不同的:在'logout'我們根本不需要'Promise'關鍵字。但是我們都需要在'fbLogin'函數中使用'Promise'關鍵字。這是爲什麼?我正在尋找的解釋是這些功能之間的差異。 – cinnaroll45

+1

如果你「等待」不是'Promise'的東西,它只能解析爲該表達式的值。例如。 'console.log(等待未定義)',記錄'未定義'。那發生在你的情況。你的'logout'返回Promise,但是這個承諾立即解決,它與'FB.logout'的實際處理無關。 –

+0

我們與'logout'處於同一頁面,如果使用'login',我們必須返回一個承諾。你能在你的答案中解釋這兩種情況的區別嗎? – cinnaroll45