【问题标题】:How to rewrite this function in FP (Ramda.js)?如何在 FP (Ramda.js) 中重写这个函数?
【发布时间】:2017-09-12 23:15:10
【问题描述】:

我有这个功能,我想知道如何用 FP 风格(使用 Ramda.js)编写它。

  1. registerUser(username, password) -> client_id, client_secret;
  2. getUserAccessToken(用户名、密码、client_id、client_secret)-> access_token、refresh_token、refreshTokenExpiresAt;
  3. 保存到存储:client_id、client_secret、access_token、refresh_token、refreshTokenExpiresAt。
async function registerUser(username: string, password: string) {
  try {
    const { client_id, client_secret } = await authAPI.registerUser(username, password);

    // get tokens
    const {
      access_token,
      refresh_token,
      refreshTokenExpiresAt,
    } = await authAPI.getUserAccessToken(username, password, client_id, client_secret);

    // save to async storage
    store.update('user', {
      client_id,
      client_secret,
      access_token,
      refresh_token,
      refreshTokenExpiresAt,
    });
  } catch (err) {
    throw Error(err);
  }
}

【问题讨论】:

    标签: javascript functional-programming ramda.js


    【解决方案1】:

    这与 Ramda 或 FP 无关。你有一个函数在做三种不同的事情(身份验证、令牌请求和持久性),这就是你的问题。

    const registered = authAPI.registerUser(username, password)
      .catch(err => showUserRegisterErr(err));
    
    const token = registered.then(({client_id, client_secret}) => {
      return Promise.all([
        Promise.resolve({client_id, client_secret}), 
        authAPI.getUserAccessToken(
          username,
          password, 
          client_id, 
          client_secret
        )
      ]);
    });
    
    const persisted = token.then((
      {client_id, client_secret},
      {access_token, refresh_token, refreshTokenExpiresAt}
    ) => {
      return store.update('user', {
        client_id,
        client_secret,
        access_token,
        refresh_token,
        refreshTokenExpiresAt,
      });
    });
    
    persisted.catch(err => { throw err; });
    

    现在这些都是常量值,而不是函数,所以让我们来解决这个问题:

    // No .catch, caller can catch errors if it wants. Also
    // no more registerUser function, it was a thin layer over
    // the auth API with error handling and we'll delegate to
    // the caller for that.
    const getToken = (username, password, registration) => {
      return registration.then(({client_id, client_secret}) => {
        return Promise.all([
          username,
          password,
          client_id,
          client_secret,
          authAPI.getUserAccessToken(
            username,
            password, 
            client_id, 
            client_secret
          )
        ]);
      });
    };
    
    const persist = datastore => ([
      client_id,
      client_secret,
      {
        access_token,
        refresh_token,
        refreshTokenExpiresAt
      }
    ]) => {
      return store.update('user', {
        client_id,
        client_secret,
        access_token,
        refresh_token,
        refreshTokenExpiresAt,
      });
    });
    
    const persistToDB = persist(store);
    const signUp = (username, password) => {
      return getToken(username, password, authAPI.registerUser(username, password))
        .then(persistToDB)
        .catch(showUserRegistrationErr);
    };
    

    现在所有不同的部分都可以独立测试了。由于注册作为参数传递给getToken,您可以使用模拟承诺对其进行测试。持久性功能也是如此。您还可以模拟 authAPI.registerUser 函数。

    除了持久化函数,函数只使用它们的参数等之外,没有状态被改变。我还参数化了数据存储,以便您可以交换持久性(或存根用于测试)。

    【讨论】:

      猜你喜欢
      • 2018-04-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-14
      • 2016-07-25
      • 1970-01-01
      • 2021-08-07
      • 2011-05-06
      • 1970-01-01
      相关资源
      最近更新 更多