promiseA+01

JS中的同步异步编程

浏览器是多线程的,JS是单线程的(浏览器只分配一个线程来执行JS)
进程大线程小:一个进程中包含多个线程,例如在浏览器中打开一个HTML页面就占用了一个进程,加载页面的时候,浏览器分配一个线程去计算DOM树,分配其它的线程去加载对应的资源文件…再分配一个线程去自上而下执行JS

  • 同步:在一个线程上(主栈/主任务队列)同一个时间只能做一件事情,当前事情完成才能进行下一个事情(先把一个任务进栈执行,执行完成,在把下一个任务进栈,上一个任务出栈…)

  • 异步:在主栈中执行一个任务,但是发现这个任务是一个异步的操作,我们会把它移除主栈,放到等待任务队列中(此时浏览器会分配其它线程监听异步任务是否到达指定的执行时间),如果主栈执行完成,监听者会把到达时间的异步任务重新放到主栈中执行…

    宏任务:macro task

    • 定时器
    • 事件绑定
    • ajax
    • 回调函数
    • Node中fs可以进行异步的I/O操作

    微任务:micro task

    • Promise(async/await) => Promise并不是完全的同步,当在Excutor中执行resolve或者reject的时候,此时是异步操作,会先执行then/catch等,当主栈完成后,才会再去调用resolve/reject把存放的方法执行
    • process.nextTick

    • 执行顺序优先级:SYNC => MICRO => MACRO

    所有JS中的异步编程仅仅是根据某些机制来管控任务的执行顺序,不存在同时执行两个任务这一说法


Promise A+

Promise 处理多个相互关联的异步请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const request = url=>{
return new Promise((resolve,reject)=>{
$.get(url,data=>{ // jquery中的ajax请求
resolve(data);
})
})
}
request(url).then(data1=>{
return request(data1.url)
}).then(data2=>{
return request(data2.url)
}).then(data3=>{
return request(data3)
}).catch(err=>{
throw new Error(err.message)
})

-------------------------------------------------------
// vue/react 都是用axios fetch 请求数据 也都支持 Promise API
import axios from 'axios';
axios.get(url).then(data => {
console.log(data)
})

promise使用

  1. Promise 是一个构造函数,new Promise 返回一个 promise对象 接收一个excutor执行函数作为参数, excutor有两个函数类型形参resolve reject
    1
    2
    3
    4
    5
    const promise = new Promise((resolve, reject) => {
    // 异步处理
    // 处理结束后、调用resolve 或 reject
    });
    // promise相当于一个状态机

promise的三种状态

  • pending
  • fulfilled
  • rejected
  1. promise 对象初始化状态为 pending
  2. 当调用resolve(成功),会由pending => fulfilled
  3. 当调用reject(失败),会由pending => rejected

    注意promsie状态 只能由 pending => fulfilled/rejected, 一旦修改就不能再变

promise对象方法

  1. then方法注册 当resolve(成功)/reject(失败)的回调函数

    1
    2
    3
    4
    // onFulfilled 是用来接收promise成功的值
    // onRejected 是用来接收promise失败的原因
    promise.then(onFulfilled, onRejected);
    // then方法是异步执行的
  2. resolve(成功) onFulfilled会被调用

    1
    2
    3
    4
    5
    6
    7
    8
    const promise = new Promise((resolve, reject) => {
    resolve('fulfilled'); // 状态由 pending => fulfilled
    });
    promise.then(result => { // onFulfilled
    console.log(result); // 'fulfilled'
    }, reason => { // onRejected 不会被调用

    })
  3. reject(失败) onRejected会被调用

    1
    2
    3
    4
    5
    6
    7
    8
    const promise = new Promise((resolve, reject) => {
    reject('rejected'); // 状态由 pending => rejected
    });
    promise.then(result => { // onFulfilled 不会被调用

    }, reason => { // onRejected
    console.log(reason); // 'rejected'
    })
  4. promise.catch

  • 在链式写法中可以捕获前面then中发送的异常
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    promise.catch(onRejected)
    // 相当于
    promise.then(null, onRrejected);

    // 注意
    // onRejected 不能捕获当前onFulfilled中的异常
    promise.then(onFulfilled, onRrejected);

    // 可以写成:
    promise.then(onFulfilled)
    .catch(onRrejected);
  1. Promise chain链式调用
  • promise.then方法每次调用 都返回一个新的promise对象 所以可以链式写法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function taskA() {
    console.log("Task A");
    }
    function taskB() {
    console.log("Task B");
    }
    function onRejected(error) {
    console.log("Catch Error: A or B", error);
    }

    var promise = Promise.resolve();
    promise
    .then(taskA)
    .then(taskB)
    .catch(onRejected) // 捕获前面then方法中的异常
  1. Promise的静态方法
  • Promise.resolve 返回一个fulfilled状态的promise对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Promise.resolve('hello').then(function(value){
    console.log(value);
    });

    Promise.resolve('hello');
    // 相当于
    const promise = new Promise(resolve => {
    resolve('hello');
    });
  • Promise.reject 返回一个rejected状态的promise对象

    1
    2
    3
    4
    Promise.reject(24);
    new Promise((resolve, reject) => {
    reject(24);
    });
  1. Promise.all 接收一个promise对象数组为参数
  • 只有全部为resolve才会调用 通常会用来处理 多个并行异步操作
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    const p1 = new Promise((resolve, reject) => {
    resolve(1);
    });

    const p2 = new Promise((resolve, reject) => {
    resolve(2);
    });

    const p3 = new Promise((resolve, reject) => {
    reject(3);
    });

    Promise.all([p1, p2, p3]).then(data => {
    console.log(data); // [1, 2, 3] 结果顺序和promise实例数组顺序是一致的
    }, err => {
    console.log(err);
    });
  1. Promise.race 接收一个promise对象数组为参数
  • Promise.race 只要有一个promise对象进入 FulFilled 或者 Rejected 状态的话,就会继续进行后面的处理。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    unction timerPromisefy(delay) {
    return new Promise(function (resolve, reject) {
    setTimeout(function () {
    resolve(delay);
    }, delay);
    });
    }
    var startDate = Date.now();

    Promise.race([
    timerPromisefy(10),
    timerPromisefy(20),
    timerPromisefy(30)
    ]).then(function (values) {
    console.log(values); // 10
    });
  1. Promise的finally
    1
    2
    3
    4
    5
    6
    7
    Promise.prototype.finally = function (callback) {
    let P = this.constructor;
    return this.then(
    value => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
    );
    };
-------------本文结束感谢您的阅读-------------