es6(下)

目录

9. Promise、async和await

Promise

 三种状态:

执行顺序

async和await

async await执行顺序 

 拓展:宏任务与微任务 

10.Proxy()代理

 语法:

proxy()所支持的所有拦截行为:

Proxy.revocable() 

 this指向问题


9. Promise、async和await

Promise

异步编程的一种解决方案。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。

 三种状态:

pending(进行中)、fulfilled(已成功)和 rejected(已失败)

除了异步操作的结果,任何其他操作都无法改变这个状态。

Promise 对象只有:从 pending 变为 fulfilled 和从 pending 变为 rejected 的状态改变。

只要处于 fulfilled 和 rejected ,状态就不会再变了即 resolved(已定型)。

const p1 = new Promise(function (resolve, reject) {
    resolve('success1');
});
const p2 = new Promise(function (resolve, reject) {
    reject('reject');
});
p1.then(function (value) {
    console.log(value); // success1
});
// 链式调用
p2.catch(function (value) {
    console.log(value); // success3
    return 123;
}).then((res) => console.log(123));

执行顺序

    <script>
        console.log(1)
        const p = new Promise((resolve) => {
          console.log(2)
          resolve()
        })
        console.log(3)
        setTimeout(() => {
          console.log(4)
        }, 0)
        p.then(() => console.log(5))
        setTimeout(() => {
          console.log(6)
        }, 0)
        console.log(7)
    </script>

 

async和await

async 是 ES7 才有的与异步操作有关的关键字, 配合await,可以让异步代码变同步

async 函数中可能会有 await 表达式.

async 函数执行时,如果遇到 await 就会先暂停执行 ,等到触发的异步操作完成后,恢复 async 函数的执行并返回解析值。

await 关键字仅在 async function 中有效。如果在 async function 函数体外使用 await ,你只会得到一个语法错误。

function testAwait (x) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(x);
    }, 2000);
  });
}
 
async function helloAsync() {
  var x = await testAwait ("hello world");
  console.log(x); 
}
helloAsync ();
// hello world

async await执行顺序 

        async function async1() {
            console.log('async1 start')
            await async2()
            console.log('async1 end')
        }
        async function async2() {
             console.log('async2')
        }
        async1()
        console.log('script start')

 拓展:宏任务与微任务 

宏任务主代码块、setTimeout、setInterval、DOM事件、AJAX请求。  

微任务MutationObserver、async/await、process.nextTick、Promise.then catch finally

js中的同步与异步

js宏任务微任务

 promise 宏任务微任务
promise,async,await,setTimeOut()执行顺序  

promise 应用场景

  await和then 


10.Proxy()代理

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。

 语法

var proxy = new Proxy(target, handler);

 Proxy 对象的所有用法,都是上面这种形式,不同的只是handler参数的写法。

  • new Proxy()表示生成一个Proxy实例,
  • target参数表示所要拦截的目标对象,
  • handler参数也是一个对象,用来定制拦截行为。
var proxy = new Proxy({}, {
  get: function(target, propKey) {
    return 35;
  }
});

proxy.time // 35
proxy.name // 35
proxy.title // 35

 :要使得Proxy起作用,必须针对Proxy实例(上例是proxy对象)进行操作,而不是针对目标对象(上例是空对象)进行操作。

var target = {};
var handler = {};
var proxy = new Proxy(target, handler);
proxy.a = 'b';
target.a // "b"

 :如果handler未进行拦截行为,则访问proxy就相当于直接操作target对象。

proxy()所支持的所有拦截行为:

  • get(target, propKey, receiver):拦截对象属性的读取,比如proxy.fooproxy['foo']
  • set(target, propKey, value, receiver):拦截对象属性的设置,比如proxy.foo = vproxy['foo'] = v,返回一个布尔值。
  • has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值。
  • deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值。
  • ownKeys(target):拦截Object.getOwnPropertyNames(proxy)Object.getOwnPropertySymbols(proxy)Object.keys(proxy)for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
  • getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
  • defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)Object.defineProperties(proxy, propDescs),返回一个布尔值。
  • preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个布尔值。
  • getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象。
  • isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值。
  • setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
  • apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)proxy.call(object, ...args)proxy.apply(...)
  • construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)

Proxy.revocable() 

Proxy.revocable()方法返回一个可取消的 Proxy 实例。

let target = {};
let handler = {};

let {proxy, revoke} = Proxy.revocable(target, handler);

proxy.foo = 123;
proxy.foo // 123

revoke();
proxy.foo // TypeError: Revoked

Proxy.revocable()方法返回一个对象,该对象的proxy属性是Proxy实例,revoke属性是一个函数,可以取消Proxy实例。上面代码中,当执行revoke函数之后,再访问Proxy实例,就会抛出一个错误。

Proxy.revocable()的一个使用场景是,目标对象不允许直接访问,必须通过代理访问,一旦访问结束,就收回代理权,不允许再次访问。

 this指向问题

虽然 Proxy 可以代理针对目标对象的访问,但它不是目标对象的透明代理,即不做任何拦截的情况下,也无法保证与目标对象的行为一致。主要原因就是在 Proxy 代理的情况下,目标对象内部的this关键字会指向 Proxy 代理。

const target = {
  m: function () {
    console.log(this === proxy);
  }
};
const handler = {};

const proxy = new Proxy(target, handler);

target.m() // false
proxy.m()  // true
  • 一旦proxy代理targettarget.m()内部的this就是指向proxy,而不是target。所以,虽然proxy没有做任何拦截,target.m()proxy.m()返回不一样的结果。
  • 如果target目标对象的属性保存在外部对象当中,当proxy代理进行目标对象取值时,this指向proxy也会取不到对应值。
  • 有些原生对象的内部属性,只有通过正确的this才能拿到,所以 Proxy 也无法代理这些原生对象的属性。例如getDate()方法只能在Date对象实例上面拿到,如果this不是Date对象实例就会报错。

this绑定原始对象,就可以解决原生对象的this问题

const target = new Date('2015-01-01');
const handler = {
  get(target, prop) {
    if (prop === 'getDate') {
      return target.getDate.bind(target);
    }
    return Reflect.get(target, prop);
  }
};
const proxy = new Proxy(target, handler);

proxy.getDate() // 1

此外,proxy代理中的内部拦截行为(以上所有支持的拦截)的this指向都是handler拦截对象。

阮一峰的proxy

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值