异步编程
2020-04-16 11:10:15 0 举报
AI智能生成
为你推荐
查看更多
前端异步编程(promise->async/await)
作者其他创作
大纲/内容
generator 函数
特点是可以暂停
两个关键词
*
yield
示例
function* read(){ yield 1; yield 2; yield 3;}let it=read()console.log(it.next())
应用
生成迭代器
Array.from vs [...likeArray]
展开运算符需要 likeArray 对象中实现迭代器
不使用 generator
使用 generator
iterator.next() 传参
function* read() { let a = yield \"hello\"; console.log(a); let b = yield \"world\"; console.log(b);}let it = read();console.log(it.next()); // 第一次 next 方法传递的参数没有任何意义console.log(it.next(1)); // 会传递给上一次 yield 的返回值console.log(it.next(2));
co 库
async + await
async function
async function 用来定义一个返回 AsyncFunction 对象的异步函数。异步函数是指通过事件循环异步执行的函数,它会返回一个隐式的 Promise 作为结果。但它的语法和结构会更像是标准的同步函数。你还可以使用 异步函数表达式 来定义异步函数。
语法
返回值
返回一个 Promise,它将会用异步函数的返回值来 resolved,或者用异步函数内部没有捕捉到的错误来 rejected。
描述
异步函数可以包含await指令,该指令会暂停异步函数的执行,并等待 Promise 的 resolution,然后继续执行异步函数,并返回结果。记住,await 关键字只在异步函数内有效。如果你在异步函数外使用它,会抛出语法错误。注意,当异步函数暂停时,调用它的函数会继续执行(收到异步函数返回的隐式Promise)async/await的目的是简化同时使用多个 promise,并对一组 Promises执行某些操作。正如Promises类似于结构化回调,async/await更像结合了 generators 和 promises 。
async/await vs Promise.then and error handling
大多数异步函数也可以使用Promises编写。但是,async 函数更容易捕获异常错误。
上面例子中的 concurrentStart 函数和 concurrentPromise 函数在功能上都是等效的。在concurrentStart函数中,如果任一 await 调用失败,它将自动捕获异常,异步函数执行中断,并通过隐式返回 Promise 将错误传递给调用者。在 Promise 例子中这种情况同样会发生,该函数必须返回一个捕获函数完成的 Promise。在 concurrentPromise 函数中,这意味着它从 Promise.all([]).then() 返回一个 Promise。事实上,此示例的先前版本忘记了这样做!
但是,async 函数仍有可能错误地忽略错误。以 parallel 异步函数为例。 如果它没有 await(或 return )Promise.all([]) 调用的结果,则不会传播任何错误。虽然 parallelPromise 示例看起来很简单,但它根本没有处理错误!处理错误需要一个类似的 return Promise.all([]) 。
async function parallel() { console.log('==PARALLEL with await Promise.all==') // Start 2 \"jobs\
The return value of an async function is implicitly wrapped in Promise.resolve.
return foo; vs return await foo;
await 操作符
await 操作符用于等待一个Promise 对象。它只能在异步函数 async function 中使用。
await 表达式会暂停当前 async function 的执行,等待 Promise 处理完成。若 Promise 正常处理(fulfilled),其回调的 resolve 函数参数作为 await 表达式的值,继续执行 async function。若 Promise rejected,await 表达式会把 Promise 的异常原因抛出。如果 await 操作符后的表达式的值不是一个 Promise,它会被转化成一个 resolved Promise.
控制台输出:Promise {<pending>}7710
异步编程
技术准备
高阶函数
定义
函数的参数是一个函数
函数返回了一个函数
常见应用
装饰者模式AOP 面向切片编程中的一些例子Aspect Oriented Programming
调用多少次后让回调函数执行
发展史
callback -> promise -> generator -> async + await
Promise
使用 Promise
链式调用
then() 函数会返回一个全新的 Promise,和原来的不同
⚠️注意:一定要有返回值,否则,callback 将无法获取上一个 Promise 的结果
使用 Promise 时的约定(规范)
传递到 then() 中的函数被置入了一个微任务队列,而不是立即执行,这意味着它是在 本轮 Javascript event loop(事件循环)运行完成 之后调用的通过 then() 添加的回调函数总会被调用,即便它是在异步操作完成之后才被添加的函数。通过多次调用 then(),可以添加多个回调函数,它们会按照插入顺序一个接一个独立执行。
错误传递
一旦异常抛出,浏览器就会查找链中的 .catch() 处理器或者 onRejected
Promise 拒绝事件
当 Promise 被拒绝时,会有下文所述的两个事件之一被派发到全局作用域。这两个事件如下所示:rejectionhandled当 Promise 被拒绝、并且在 reject 函数处理该 rejection 之后会派发此事件。unhandledrejection当 Promise 被拒绝,但没有提供 reject 函数来处理该 rejection 时,会派发此事件。
PromiseRejectionEvent 的两个属性
promise 属性,该属性指向被驳回的 Promisereason 属性,该属性用来说明 Promise 被驳回的原因
我们可以通过以上事件为 Promise 失败时提供补偿处理,也有利于调试 Promise 相关的问题。在每一个上下文中,该处理都是全局的,因此不管源码如何,所有的错误都会在同一个handler中被捕捉处理。一个特别有用的例子:当你使用 Node.js 时,有些依赖模块可能会有未被处理的 rejected promises,这些都会在运行时打印到控制台。你可以在自己的代码中捕捉这些信息,然后添加与 unhandledrejection 相应的 handler 来做分析和处理,或只是为了让你的输出更整洁。举例如下:window.addEventListener(\"unhandledrejection\
组合
Promise.resolve() 和 Promise.reject() 是手动创建一个已经 resolve 或者 reject 的 Promise 快捷方法。它们有时很有用。Promise.all() 和 Promise.race() 是并行运行异步操作的两个组合式工具。
嵌套
嵌套 Promise 是一种可以限制 catch 语句的作用域的控制结构写法。明确来说,嵌套的 catch 仅捕捉在其之前同时还必须是其作用域的 failureres,而捕捉不到其嵌套域以外的 error。如果使用正确,那么可以实现高精度的错误修复。
doSomethingCritical().then(result => doSomethingOptional() .then(optionalResult => doSomethingExtraNice(optionalResult)) .catch(e => {})) // Ignore if optional stuff fails; proceed..then(() => moreCriticalStuff()).catch(e => console.log(\"Critical failure: \" + e.message));// 没有输出⚠️ 注意:如果 doSomethingCritical() 失败,这个错误仅会被最后的(外部)catch 语句捕获到。
常见错误
// 错误示例,包含 3 个问题!doSomething().then(function(result) { doSomethingElse(result) // 没有返回 Promise 以及没有必要的嵌套 Promise .then(newResult => doThirdThing(newResult));}).then(() => doFourthThing());// 最后,是没有使用 catch 终止 Promise 调用链,可能导致没有捕获的异常
第一个错误是没有正确地将事物相连接。当我们创建新 Promise 但忘记返回它时,会发生这种情况。这种情况下,链条被打破,或者说,我们有两个独立的链条竞争。这意味着 doFourthThing() 不会等待 doSomethingElse() 与 doThirdThing() 完成,将与它们并行运行。单独的链有单独的错误处理,导致未捕获的错误。
第二个错误是不必要地嵌套,导致了第一个错误。嵌套还限制了内部错误处理程序的范围,如果是非预期的,可能会导致未捕获的错误。
第三个错误是忘记用 catch 终止链。未终止的 promise 链会导致未被捕捉的 promise rejections。
参数
executor
1. executor是带有 resolve 和 reject 两个参数的函数 。2. Promise构造函数执行时立即调用executor 函数, resolve 和 reject 两个函数作为参数传递给executor(executor 函数在Promise构造函数返回所建promise实例对象前被调用)。3. resolve 和 reject 函数被调用时,分别将promise的状态改为fulfilled(完成)或rejected(失败)。4. executor 内部通常会执行一些异步操作,一旦异步操作执行完毕(可能成功/失败),要么调用resolve函数来将promise状态改成fulfilled,要么调用reject 函数将promise的状态改为rejected。5. 如果在executor函数中抛出一个错误,那么该promise 状态为rejected。6. executor函数的返回值被忽略。
Promise 对象是一个代理对象,被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值:不是立即返回最终执行结果,而是返回一个promise对象,其在未来某个时候能够提供值
Promise 的三种状态
pending: 初始状态,既不是成功,也不是失败状态。fulfilled: 意味着操作成功完成。rejected: 意味着操作失败。
pending 状态的 Promise 对象可能会变为fulfilled 状态并传递一个值给相应的状态处理方法,也可能变为失败状态(rejected)并传递失败信息。当其中任一种情况出现时,Promise 对象的 then 方法绑定的处理方法(handlers )就会被调用(then方法包含两个参数:onfulfilled 和 onrejected,它们都是 Function 类型。当Promise状态为fulfilled时,调用 then 的 onfulfilled 方法,当Promise状态为rejected时,调用 then 的 onrejected 方法, 所以在异步操作的完成和绑定处理方法之间不存在竞争)。因为 Promise.prototype.then 和 Promise.prototype.catch 方法返回promise 对象, 所以它们可以被链式调用。
方法
1. Promise.all(iterable)
Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。
iterable
一个可迭代对象,如 Array 或 String
如果传入的参数是一个空的可迭代对象,则返回一个已完成(already resolved)状态的 Promise。如果传入的参数不包含任何 promise,则返回一个异步完成(asynchronously resolved) Promise。注意:Google Chrome 58 在这种情况下返回一个已完成(already resolved)状态的 Promise。其它情况下返回一个处理中(pending)的Promise。这个返回的 promise 之后会在所有的 promise 都完成或有一个 promise 失败时异步地变为完成或失败。 返回值将会按照参数内的 promise 顺序排列,而不是由调用 promise 的完成顺序决定。
手写 MyPromise.all(iterable)
MyPromise.all = function(values) {// 1. 要返回一个新的 Promise 实例font color=\"#0076b3\
2. Promise.allSettled(iterable)
3. Promise.race(iterable)
4. Promise.reject(reason)
5. Promise.resolve(value)
Promise.resolve(value)方法返回一个以给定值解析后的Promise 对象。如果该值为promise,返回这个promise;如果这个值是thenable(即带有\"then\" 方法)),返回的promise会“跟随”这个thenable的对象,采用它的最终状态;否则返回的promise将以此值完成。此函数将类promise对象的多层嵌套展平。
Promise 原型
Promise.prototype.catch(onRejected)
Promise.prototype.finally(onFinally)
手写 Promise
优缺点
优点
可以解答异步嵌套问题
解决多个异步并发问题 (指的是 all race 这些方法吗?)
缺点
基于回调 (基于回调有啥缺点呢??)
无法终止异步
规范
promiseaplus
特点
三个状态
等待(默认)
成功
一旦成功了就不能失败,反过来也一样
如果 new Promise 的时候报错,会变成失败态,后面的 resolve 函数也不会走
失败
Promise 实例都有 then 方法
实现 Promise 类
自己实现某个功能的步骤
写出此功能的核心用法与特点,即写出测试用例
根据其核心用法与特点来实现
代码地址: /Users/lucy/code/github/FE-blog/interview/js/promise.js
Promise.prototype.then()
then() 方法返回一个 Promise。它有两个参数:Promise 的成功和失败情况的回调函数。
return value
chaining
限制 promise 并发
//font color=\"#f1753f\
0 条评论
回复 删除
下一页