如何在FP(Ramda.js)中重写此函数?

时间:2017-09-12 13:26:46

标签: javascript functional-programming ramda.js

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

  
      
  1. registerUser(用户名,密码) - > client_id,client_secret;
  2.   
  3. getUserAccessToken(username,password,client_id,client_secret) - >   access_token,refresh_token,refreshTokenExpiresAt;
  4.   
  5. 保存到存储:client_id,client_secret,access_token,refresh_token,refreshTokenExpiresAt。
  6.   
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);
  }
}

1 个答案:

答案 0 :(得分:2)

这与Ramda或FP无关。你有一个功能做三个不同的事情(auth,令牌请求和持久性),那就是你的问题。

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函数。

除了持久性函数外,没有状态发生变异,函数只使用它们的参数等。我还对数据存储区进行了参数化,以便您可以交换持久性(或将其存根以进行测试)。