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([]) 参数是个数组 异步操作的并行执行的,所有都执行完成后,才会走then方法
// 谁跑的慢,以谁为准执行回调,如果其中一个出错,会立即终止,执行.catch
// 并发执行

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

  Promise.race([requestImg(), timeout()]).then(function (results) {
     
    console.log(results);
  }).catch(function (reason) {
     
    console.log(reason);
  });
Promise.all() 和  romise.race() 都具有短路特性
// Promise.allSettled([])
调试 

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)
})

你可能感兴趣的:(Javascript,html5,javascript,typescript,前端,vue.js)