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异步解决方案的发展历程以及优缺点(一面) #24

Open
littleKnave opened this issue Apr 30, 2019 · 1 comment
Assignees
Milestone

Comments

@littleKnave
Copy link

littleKnave commented Apr 30, 2019

面试公司:

滴滴

面试环节:

未知

问题:

JS异步解决方案的发展历程以及优缺点。

@littleKnave
Copy link
Author

littleKnave commented May 1, 2019

答案:

什么是异步:

当前一个任务被执行时,不会等待任务执行完成后就去执行下一个任务,等前一个任务执行完成后,将去执行其返回的回调函数,这是异步操作

为什么要用异步:

js是单线程的,因此必须等前一个任务完成后,后一个任务才会被执行。因此当执行一段耗时的程序时,会影响整个程序的执行,异步的方法就是为了解决这个问题。

解决方案:

1.回调函数callback:

被作为实参传入另一函数,并在该外部函数内被调用,用以来完成某些任务的函数。如setTimeOut,ajax请求,readFile等。
例:

function greeting(name) {
  alert('Hello ' + name);
}

function processUserInput(callback) {
  var name = prompt('请输入你的名字。');
  callback(name);
}

processUserInput(greeting);

优点:
解决了异步的问题。
缺点:
回调地狱:多个回调函数嵌套的情况,使代码看起来很混乱,不易于维护。

2.事件发布订阅

当一个任务执行完成后,会发布一个事件,当这个事件有一个或多个‘订阅者’的时候,会接收到这个事件的发布,执行相应的任务,这种模式叫发布订阅模式。如node的events,dom的事件绑定
例:

document.body.addEventListener('click',function(){
  alert('订阅了');
},false);
document.body.click(); 

优点:时间对象上的解耦。
缺点:消耗内存,过度使用会使代码难以维护和理解

3.Promise

Promise是es6提出的异步编程的一种解决方案。
Promise 对象有三种状态:

  • pending: 初始状态,既不是成功,也不是失败状态。
  • fulfilled: 意味着操作成功完成。
  • rejected: 意味着操作失败。
    promise的状态只能从pending变成fulfilled,和pending变成rejected,状态一旦改变,就不会再改变,且只有异步操作的结果才能改变promise的状态。
    例:
let promise = new Promise(function (resolve, reject) {
    fs.readFile('./1.txt', 'utf8', function (err, data) {
        resolve(data)
    })
})

promise
    .then(function (data) {
        console.log(data)
    })

优点:解决了回调地狱的问题,将异步操作以同步操作的流程表达出来。
缺点:无法取消promise。如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。当执行多个Promise时,一堆then看起来也很不友好。

4.Generator

Generator是es6提出的另一种异步编程解决方案,需要在函数名之前加一个*号,函数内部使用yield语句。Generaotr函数会返回一个遍历器,可以进行遍历操作执行每个中断点yield。
例:

function * count() {
  yield 1
  yield 2
  return 3
}
var c = count()
console.log(c.next()) // { value: 1, done: false }
console.log(c.next()) // { value: 2, done: false }
console.log(c.next()) // { value: 3, done: true }
console.log(c.next()) // { value: undefined, done: true }

优点:没有了Promise的一堆then(),异步操作更像同步操作,代码更加清晰。
缺点:不能自动执行异步操作,需要写多个next()方法,需要配合使用Thunk函数和Co模块才能做到自动执行。

5.async/await

async是es2017引入的异步操作解决方案,可以理解为Generator的语法糖,async等同于Generator和co模块的封装,async 函数返回一个 Promise。
例:

async function read() {
 let readA = await readFile('data/a.txt')
 let readB = await readFile('data/b.txt')
 let readC = await readFile('data/c.txt')

 console.log(readA)
 console.log(readB)
 console.log(readC)
}

read()

优点:内置执行器,比Generator操作更简单。async/await比*/yield语义更清晰。返回值是Promise对象,可以用then指定下一步操作。代码更整洁。可以捕获同步和异步的错误。

@acodercc acodercc added this to the 已回答 milestone May 1, 2019
@acodercc acodercc changed the title To littleKnave: JS异步解决方案的发展历程以及优缺点(滴滴) 滴滴: JS异步解决方案的发展历程以及优缺点(一面) May 6, 2019
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

2 participants