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