码迷,mamicode.com
首页 > Web开发 > 详细

[JS Compose] 3. Use chain for composable error handling with nested Eithers (flatMap)

时间:2016-12-14 07:36:47      阅读:241      评论:0      收藏:0      [点我收藏+]

标签:eal   blog   span   ant   sse   nes   else   --   cal   

We refactor a function that uses try/catch to a single composed expression using Either. We then introduce the chain function to deal with nested Eithers resulting from two try/catch calls.

 

For example we have this code using try & catch:

const getPort = () => {
  try {
    const file = fs.readFileSync(config.json);
    const c = JSON.parse(file);
    return c.port;
  } catch(e) {
    return 3000;
  }
}

 

And now, we want to use Either to rewirte the code:

// SETUP: fake fs
//==========
const fs = {
  readFileSync: name => {
    if(name === config.json) {
      return JSON.stringify({port: 8888})
    } else {
      throw(missing file!)
    }
  }
}

//=================

const Right = x => ({
    map: f => Right(f(x)),
    fold: (f, g) => g(x),
    toString: () => `Right(${x})`
  });

const Left = x => ({
  map: f => Left(x),
  fold: (f, g) => f(x),
  toString: () => `Left(${x})`
});

const fromNullable = x => 
  x != null ? Right(x): Left(null);

const tryCatch = f => {
  try {
    return Right(f());
  } catch(e) {
    return Left(e);
  }
}

//=========================
const getPort = () =>
  tryCatch(() => fs.readFileSync(config.json))
  .map(f => JSON.parse(f))
  .fold(
    x => 3000,
    x => x.port);

console.log(getPort(config.json))

 

We wrote the function ‘tryCatch‘, the idea is put the code need to be checked in try, when success call ‘Right‘, error, call ‘Left()‘.

tryCatch(() => fs.readFileSync(config.json))

Read the file, is success, will return file content. If not, then goes to set default 3000.

  .fold(
    x => 3000,
    x => x.port);

 

It works, but we still miss one things, in the old code, the ‘JSON.parse‘ are also wrapped into try catch.

const getPort = () =>
  tryCatch(() => fs.readFileSync(config.json)) //Right(‘{port:8888}‘)
  .map(f => tryCatach(() => JSON.parse(f))) //Right(Right({port:8888}))

But once we also wrap parseing code into tryCatch function, the return value is 2d-Right. So we want to flatten it.

 

const Right = x => ({
    map: f => Right(f(x)),
    flatMap: f => f(x),
    fold: (f, g) => g(x),
    toString: () => `Right(${x})`
  });

const Left = x => ({
  map: f => Left(x),
  flatMap: f => f(x),
  fold: (f, g) => f(x),
  toString: () => `Left(${x})`
});

We add ‘flatMap‘, so instead of putting the value into Right() or Left(), we just return the value. Because we know the value passed in is already a Right or Left.

 

const getPort = () =>
  tryCatch(() => fs.readFileSync(config.json)) //Right(‘{port:8888}‘)
  .flatMap(f => tryCatch(() => JSON.parse(f))) //Right({port:8888})
  .fold(
    x => 3000,
    x => x.port);

 

 

---------

// SETUP: fake fs
//==========
const fs = {
  readFileSync: name => {
    if(name === config.json) {
      return JSON.stringify({port: 8888})
    } else {
      throw(missing file!)
    }
  }
}

//=================

const Right = x => ({
    map: f => Right(f(x)),
    flatMap: f => f(x),
    fold: (f, g) => g(x),
    toString: () => `Right(${x})`
  });

const Left = x => ({
  map: f => Left(x),
  flatMap: f => f(x),
  fold: (f, g) => f(x),
  toString: () => `Left(${x})`
});

const fromNullable = x => 
  x != null ? Right(x): Left(null);

const tryCatch = f => {
  try {
    return Right(f());
  } catch(e) {
    return Left(e);
  }
}

//=========================
const getPort = () =>
  tryCatch(() => fs.readFileSync(config.json)) //Right({port:8888})
  .flatMap(f => tryCatch(() => JSON.parse(f))) //Right(Right({port:8888}))
  .fold(
    x => 3000,
    x => x.port);

console.log(getPort(config.json))

 

[JS Compose] 3. Use chain for composable error handling with nested Eithers (flatMap)

标签:eal   blog   span   ant   sse   nes   else   --   cal   

原文地址:http://www.cnblogs.com/Answer1215/p/6175746.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!