Asynchronous(异步处理-Promise)

为什么使用Promise?

解决 更好的解决回调问题,减少嵌套;

什么是Promise?
从语法上说,Promise 是一个对象,从它可以获取异步操作的消息;
Promise 必须为以下三种状态之一:

等待态(Pending):初始状态,既没有被完成,也没有被拒绝
执行态(Fulfilled):操作成功完成
拒绝态(Rejected):操作失败

一旦Promise 被 resolve 或 reject,不能再迁移至其他任何状态(即状态 immutable)。
基本过程:
    1. 初始化 Promise 状态(pending)
    2. 立即执行 Promise 中传入的 fn 函数,将Promise 内部 resolve、reject 函数作为参数传递给 fn ,按事件机制时机处理    
    3. 执行 then(..) 注册回调处理数组(then 方法可被同一个 promise 调用多次)
    4. Promise里的关键是要保证,then方法传入的参数 onFulfilled 和 onRejected,必须在then方法被调用的那一轮事件循环之后的新执行栈中执行。
//  Promise

 new Promise(
    function (resolve, reject) {
      resolve('成功')
      reject('失败')
    }
  );
缺点
    promise一旦创建,无法取消

    .then方法每次调用都会创建一个新的promise对象,一定程度上造成了内存的浪费
Promise方法总结
all参数所有结果返回成功才返回
allSettled参数不论返回结果,都返回每个参数的执行状态
any参数只要一个成功,就返回该成功的执行结果
race返回最先执行成功的执行结果
// Promise.all([]) 参数是个数组 异步操作的并行执行的,所有都执行完成后,才会走then方法
// 谁跑的慢,以谁为准执行回调,如果其中一个出错,会立即终止,执行.catch
// 并发执行

  Promise.all([async1(), async2(), async3()]).then(function (results) {
    console.log(results);
  });
// Promise.race([])
// 谁跑的快,以谁为准执行回调

  //请求某个图片资源
  function requestImg() {
    var p = new Promise(function (resolve, reject) {
      var img = new Image();
      img.onload = function () {
        resolve(img);
      };
      img.src = 'http://www.baidu.com/img/flexible/logo/pc/result.png';
    });
    return p;
  }
  //延时函数,用于给请求计时
  function timeout() {
    var p = new Promise(function (resolve, reject) {
      setTimeout(function () {
        reject('图片请求超时');
      }, 5000);
    });
    return p;
  }
  Promise.race([requestImg(), timeout()])
    .then(function (results) {
      console.log(results);
    })
    .catch(function (reason) {
      console.log(reason);
    });
Promise.all() 和  romise.race() 都具有短路特性
// Promise.allSettled([])
// 全部处理完成后,我们可以拿到每个 Promise 的状态,而不管其是否处理成功

  const resolved = Promise.resolve(2);
  const rejected = Promise.reject(-1);
  const allSettledPromise = Promise.allSettled([resolved, rejected]);
  allSettledPromise.then(function (results) {
    console.log(results);
  });
  // 返回结果:
  // [
  //    { status: 'fulfilled', value: 2 },
  //    { status: 'rejected', reason: -1 }
  // ]
// Promise.any([])
// 只要参数 Promise 实例有一个变成 fulfilled 状态,则any 返回的实例就会变成 fulfilled 状态;
// 如果所有参数 Promise 实例都变成 rejected 状态,包装实例就会变成 rejected 状态。

  const pErr = new Promise((resolve, reject) => {
    reject('总是失败');
  });

  Promise.any([pErr]).catch((err) => {
    console.log(err); // "AggregateError: No Promise in Promise.any was resolved"
  });```

```typescript
调试 

Promise 有两个问题:

    不能在返回表达式的箭头函数中设置断点;
    在 then 代码块中设置断点,调试器不会跳到下一个 then,因为它只会跳过异步代码;
// 在 .then 里面 return 一个 Promise

.then(r => {
    return serverStatusPromise(r); // 返回 { statusCode: 200 } 的 Promise
})
.then(resp => {
    console.log(resp.statusCode); // 200; 注意自动解析的 promise
})
// 每次执行 .then 的时候都会自动创建一个新的 Promise
// 所以promise可以链式调用

var statusProm = fetchServerStatus();

var promA = statusProm.then(r => (r.statusCode === 200 ? "good" : "bad"));

var promB = promA.then(r => (r === "good" ? "ALL OK" : "NOTOK"));

var promC = statusProm.then(r => fetchThisAnotherThing());
// 对调用者来说,Promise 的 resolved/rejected 状态是唯一的,调用者,只可能接收到一种状态
// Promise 构造函数不是解决方案

// 错误
return new Promise((res, rej) => {
  fs.readFile("/etc/passwd", function(err, data) {
    if (err) return rej(err);
    return res(data);
  });
});

// Promise 构造函数 只是想要把回调转换成 Promise 时使用。


// 正确
return fs.readFile("/etc/passwd", function(err, data) {
    if (err) return err;
    return data;
  });

// 用 Promise 构造函数 封装 Promise 是多余的,并且违背了 Promise 本身的目的。
// 使用 Promise.resolve

var similarProm = new Promise(res => res(5));
// ^^ 等价于
var prom = Promise.resolve(5);


// 当不确定它是一个 Promise 还是一个普通的值的时候,可以做一个安全的封装。

function goodProm(maybePromise) {
  return Promise.resolve(maybePromise);
}

goodProm(5).then(console.log); // 5

var sixPromise = fetchMeNumber(6);

goodProm(sixPromise).then(console.log); // 6

goodProm(Promise.resolve(Promise.resolve(5))).then(console.log); // 5, 注意,它会自动解析所有的 Promise!
// 使用 Promise.reject

var rejProm = new Promise((res, reject) => reject(5));

rejProm.catch(e => console.log(e)) // 5


// 提前使用 Promise.reject 拒绝执行
function foo(myVal) {
    if (!mVal) {
        return Promise.reject(new Error('myVal is required'))
    }
    return new Promise((res, rej) => {
        // 从你的大回调到 Promise 的转换!
    })
}
// 不要害怕 reject,也不要在每个 .then 后面加冗余的 .catch

// 解决 reject

.then(() => 5.length) // <-- 这里会报错
.catch(e => {
        return 5;  // <-- 重新使方法正常运行
})
.then(r => {
    console.log(r); // 5
})
.catch(e => {
    console.error(e); // 这个方法永远不会被调用 :)
})


// 拒绝一个 reject

.then(() => 5.length) // <-- 这里会报错
.catch(e => {
  errorLogger(e); // 做一些错误处理
  return Promise.reject(e); // 拒绝它,是的,你可以这么做!
})
.then(r => {
    console.log(r); // 这个 .then (或者任何后面的 .then) 将永远不会被调用,因为我们在上面使用了 reject :)
})
.catch(e => {
    console.error(e); //<-- 它变成了这个 catch 方法的问题
})


// .then(data,err) 和 .then(data).catch(err) 的区别

.then(function() {
   return Promise.reject(new Error('something wrong happened'));
}).catch(function(e) {
   console.error(e); // something wrong happened
});


.then(function() {
   return Promise.reject(new Error('something wrong happened'));
}, function(e) { // 这个回调处理来自当前 `.then` 方法之前的错误
    console.error(e); // 没有错误被打印出来
});


 let promise = new Promise((resolve, reject) => {
   setTimeout(resolve, 500, 'promise');
});
promise.then((value) => {
   console.log(value);    //promise
   throw '抛出一个异常'     //通过throw 抛出
}).catch((e) => {
   console.log(e)    //输出: 抛出一个异常
})
// 避免.then回调地狱

使用Async/Await


.then(myVal => {
    const promA = foo(myVal);
    const promB = anotherPromMake(myVal);
    return Promise.all([prom, anotherProm])
})
.then(([valA, valB]) => {   // 很好的使用 ES6 解构
    console.log(valA, valB) // 所有解析后的值
    return hungryFunc(valA, valB)
})
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值