Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS之最佳实践(1) #15

Open
akira-cn opened this issue Aug 13, 2019 · 2 comments
Open

JS之最佳实践(1) #15

akira-cn opened this issue Aug 13, 2019 · 2 comments

Comments

@akira-cn
Copy link
Owner

akira-cn commented Aug 13, 2019

Programs are meant to be read by humans and only incidentally for computers to execute.

—— Donald Knuth

今天在微信群里看到一个问题:

如何实现一个函数,使得 repeat(() => {console.log('1')}, 5, 2000) 每两秒执行一次打印,总共五次?

这个问题当然不难,使用定时器就可以了,基本上会写JS的同学都能解决这个问题。在ES2017之前,实现方法也有很多,但现在都9102年了,如果是我来实现的话,基本上毫不犹豫写下面的代码:

function wait(millisecond) {
  return new Promise((resolve) => {
    setTimeout(resolve, millisecond);
  });
}

async function repeat(task, count = 1, millisecond = 0) {
  while(count--) {
    await wait(millisecond);
    task();
  }
}

为什么这样写呢?因为这个代码结构极其简单,while循环基本上学过程序开发的新手都能理解,只要再了解一下async/await的语义(实际上猜都能猜到),就能彻底明白代码的含义:

  while(count--) {
    await wait(millisecond);
    task();
  }

循环count次,每次wait若干毫秒,这个代码逻辑简单到不需要任何注释。

使用也非常方便,因为它自身是async的函数,返回promise,所以如果我们需要等待执行完成后执行其他任务,只需要放到async function中并加上await:

(async function() {
  await repeat(taskA, 5, 2000);
  taskB();
 }());

反之,如果我们希望任务同步执行,只需要去掉await。

repeat(taskA, 5, 2000);
taskB();

如果我们希望A、B都重复若干次,且A、B先后依次执行:

await repeat(taskA, 5, 2000);
await repeat(taskB, 5, 2000);

如果我们希望A、B都重复若干次,且并行执行:

await Promise.all([repeat(taskA, 5, 2000), repeat(taskB, 5, 2000)])

如果我们希望taskA、taskB也可以是异步方法,可以稍微修改一下repeat实现:

async function repeat(task, count = 1, millisecond = 0) {
  while(count--) {
    await wait(millisecond);
    await task();
  }
}

总之,代码是给人阅读的,在ES2017之后,JavaScript支持了async function,请大家在处理异步操作时,使用async function,这样能够写出简洁的,让人非常容易阅读和理解的代码来。

关于async/await的最佳实践,大家还有什么想法,欢迎在issue中讨论。

@cllemon
Copy link

cllemon commented Aug 26, 2019

异常处理

async function asyncMethod() {
   try {
     // normal: todo
   } catch (error) {
     // error: todo
   }
}
async function asyncMethod() {
   try {
     loading = true; // 数据请求态
   } catch (error) {
     console.log(error);
   } finally {
     loading = false; // 数据请求完成
   }
}
  • 这种处理是必要的,但在遇到的大多数代码仅仅只是打印了错误。
    • 强烈建议部署前端异常监控,如:在 catch 内部署特定异常监控代码等...
    • 可通过高阶函数或webpack插件在转译时注入。但这种处理方式多少有失灵活。
  • 还有没有更好的实现方式去处理异常呢❓

@hax
Copy link

hax commented Aug 26, 2019

@cllemon 异常该怎么处理就怎么处理。在catch内部署异常监控(catch之后log然后rethrow)是不必要的,因为你可以用onerror、onunhandledrejection 之类的来统一处理。唯一的例外是老ie/edge不支持跨源脚本onerror时不得已为之。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants