We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
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 的异步编程中,我们经常会遇到一个问题,就是回调函数嵌套回调函数,所谓的 Callback Hell 回调地狱。因为很多时候我们会有这样的需求,第二个异步任务需要第一个异步任务执行完成的数据才能开始,而第三个异步任务又需要第二个任务的数据,这样使得他们不得不链式执行。
Callback Hell
在 ES6 的 Promise 出现之前,我们会试着用递归的方式使得代码更加扁平化:
function sequence (arr, initData) { function next(data) { if (arr.length <= 0) return arr.shift()(data, next) } next(initData); }
sequence 函数参数 arr 是一个回调函数数组,里面存放将要按序执行的回调函数
initData 是传递给第一个将要执行的函数
真正执行函数的语句是,arr.shift()(data, next)。使用数组的栈方法 shift() 每次从数组中取出第一个回调函数出来执行。这里需要每个回调函数里面调用 next() 这个回调函数,用于决定下一个回调函数执行的时机
你会发现,其实 next 就是一个闭包,因为 next 通过参数的形式暴露出去,next 函数可以访问到作用域链上的 arr 数组
下面看看如何调用:
sequence([ function (data, next) { setTimeout(function () { console.log(data) next(data + 1) }, Math.random() * 5 * 1000) }, function (data, next) { console.log(data) next(data + 1) }, function (data, next) { setTimeout(function () { console.log(data) }, 0) } ], 1)
then 是 promise 原型上的方法,即,Promise.prototype.then(),then 函数的参数,是 promise 对象 resolve 状态的回调函数,而 then() 函数返回值也是一个 promise 对象,因此可以使用链式的 then 写法实现回调函数的链式调用
function getData(data) { return new Promise(resolve => { setTimeout(() => { data++; resolve(data); }, 2000); }) } getData(1) .then(data => { console.log(data); return getData(data); }) .then(data => { console.log(data); return getData(data); }) .then(data => { console.log(data); return getData(data); }) .then(data => { console.log(data) });
但问题来了,假如我们不知道有多少个回调函数将要被执行,怎么办?
又或者,有一组回调函数,我们需要批量写出一个链式调用链
function getData(data) { return new Promise(resolve => { setTimeout(() => { data++; resolve(data); }, 2000); }) } let arr = [ data => { console.log(data); return getData(data); }, data => { console.log(data); return getData(data); }, data => { console.log(data); return getData(data); }, data => { console.log(data); } ] arr.reduce((promise, callback) => { return promise.then(callback); }, getData(1));
有了 async 和 await 语法糖,我们可以很方便实现链式调用
await 后面一般跟 promise 对象,如果不是 promise 对象,会被 Promise.resolve() 做转换
await 必须写在 async 函数里,await 会阻塞后面语句,必须等到 promise 的状态变为 resolve 之后,才会继续往下执行
function getData(data) { return new Promise(resolve => { setTimeout(() => { data++; resolve(data); }, 2000); }) } (async function seq(d0) { let d1 = await getData(d0); let d2 = await getData(d1); let d3 = await getData(d2); let d4 = await getData(d3) console.log(d4); })(1)
拓展一下 async / await 错误处理
只要一个 await 语句后面的 Promise 变为 reject,那么整个 async 函数都会中断执行,所以使用 try...catch 或 catch 捕获异常
await
Promise
reject
async
try...catch
catch
async function myFunction() { try { await somethingThatReturnsAPromise(); } catch (err) { console.log(err); } } // 另一种写法 async function myFunction() { await somethingThatReturnsAPromise() .catch(function (err) { console.log(err); }); }
AymaxLi/AymaxLi.github.io#2
http://es6.ruanyifeng.com/#docs/async#%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95
The text was updated successfully, but these errors were encountered:
No branches or pull requests
# 抛出问题
在 JS 的异步编程中,我们经常会遇到一个问题,就是回调函数嵌套回调函数,所谓的
Callback Hell
回调地狱。因为很多时候我们会有这样的需求,第二个异步任务需要第一个异步任务执行完成的数据才能开始,而第三个异步任务又需要第二个任务的数据,这样使得他们不得不链式执行。# 递归链式调用
在 ES6 的 Promise 出现之前,我们会试着用递归的方式使得代码更加扁平化:
sequence 函数参数 arr 是一个回调函数数组,里面存放将要按序执行的回调函数
initData 是传递给第一个将要执行的函数
真正执行函数的语句是,arr.shift()(data, next)。使用数组的栈方法 shift() 每次从数组中取出第一个回调函数出来执行。这里需要每个回调函数里面调用 next() 这个回调函数,用于决定下一个回调函数执行的时机
你会发现,其实 next 就是一个闭包,因为 next 通过参数的形式暴露出去,next 函数可以访问到作用域链上的 arr 数组
下面看看如何调用:
# Promise then
then 是 promise 原型上的方法,即,Promise.prototype.then(),then 函数的参数,是 promise 对象 resolve 状态的回调函数,而 then() 函数返回值也是一个 promise 对象,因此可以使用链式的 then 写法实现回调函数的链式调用
但问题来了,假如我们不知道有多少个回调函数将要被执行,怎么办?
又或者,有一组回调函数,我们需要批量写出一个链式调用链
# async / await
有了 async 和 await 语法糖,我们可以很方便实现链式调用
await 后面一般跟 promise 对象,如果不是 promise 对象,会被 Promise.resolve() 做转换
await 必须写在 async 函数里,await 会阻塞后面语句,必须等到 promise 的状态变为 resolve 之后,才会继续往下执行
拓展一下 async / await 错误处理
只要一个
await
语句后面的Promise
变为reject
,那么整个async
函数都会中断执行,所以使用try...catch
或catch
捕获异常# 参考
AymaxLi/AymaxLi.github.io#2
http://es6.ruanyifeng.com/#docs/async#%E5%9F%BA%E6%9C%AC%E7%94%A8%E6%B3%95
The text was updated successfully, but these errors were encountered: