• promise怎么用?promise的各种使用方法及理解?


    Promise - “承诺”

    Promise 是ES6对异步编程的一种解决方案,比传统的解决方案(回调函数和事件)更合理更强大。
    Promise 简单说就是一个容器,里面保存着一个尚未完成且预计在未来完成的异步操作。

    Promise 是一个构造函数,用来创建一个Promise对象。

    Promise对象代表一个异步操作,有三种状态:
    pending(进行中)
    fulfilled(成功)
    rejected(失败)

    Promise 对象的状态改变有两种:
    从 pending 变为 fulfilled
    从 pending 变为 rejected

    一旦状态改变,就不会再变,任何时候都可以得到这个结果。
    有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。

    var p = new Promise(function(resolve, reject) {
      // do something ...
      if (/* 异步操作成功 */){
        resolve(value);
      } else {
        reject(error);
      }
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。
    resolve 和 reject 是两个函数,由 JavaScript 引擎提供,不用自己部署。

    resolve 函数的作用是,将Promise对象的状态从“进行中”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去。

    reject 函数的作用是,将Promise对象的状态从“进行中”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

    p.then(function(value) {
      // success
    }, function(error) {
      // failure  可选
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Promise实例的then方法:
    第一个参数是resolved状态的回调函数
    第二个参数(可选)是rejected状态的回调函数
    方法返回的是一个新的Promise实例

    Promise实例的catch方法:用于指定发生错误时的回调函数,可以捕获then里面的错误。

    throw new Error(‘出错啦’);

    不管promise最后的状态,在执行完then或catch指定的回调函数以后,都会执行finally方法指定的回调函数。

    Promise.all 可以将多个Promise实例包装成一个新的Promise实例。
    1.它接受一个数组作为参数。
    2.数组可以是Promise对象,也可以是其它值,只有Promise会等待状态改变。
    3.当所有的子Promise都完成,该Promise完成,返回值是全部值的数组。

    Promise.all([p1,p2,p3]).then(function (arr){
        console.log(arr);
    },function (error){
        console.log(error);
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Promise.race 类似于Promise.all,区别在于它有任意一个完成就算完成(无论成功或失败)

    1.Promise 改造 函数嵌套

    2.Promise 改造 ajax嵌套依赖

    Generator 遍历器生成函数

    Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。

    语法上,首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。
    形式上,Generator 函数是一个普通函数,但是有两个特征:
    一是,function关键字与函数名之间有一个星号 *;二是,函数体内部使用yield表达式,定义不同的内部状态(yield 即“产出”)。

    // Generator 遍历器生成函数
    function* myGenerator(){
        yield 'hello';
        yield 'world';
        yield 'result';
    }
    var iterator = myGenerator();
    console.log( iterator ); // 遍历器对象(Iterator Object)
    console.log( iterator.next() ); // {value: "hello", done: false}
    console.log( iterator.next() ); // {value: "world", done: false}
    console.log( iterator.next() ); // {value: "result", done: false}
    console.log( iterator.next() ); // {value: undefined, done: true}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    执行 Generator 函数会返回一个遍历器对象,是一个遍历器对象生成函数。
    每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。
    value表示当前的内部状态的值,是yield后面那个表达式的值;done是一个布尔值,表示是否遍历结束。
    Generator 函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,其实是提供了一种可以暂停执行的函数。yield表达式就是暂停标志。

    for…of循环,扩展运算符(…)等方法,内部调用的都是遍历器接口。

    任意一个对象的Symbol.iterator方法(数组,字符串, Set,Map,元素集合,arguments),等于该对象的遍历器生成函数( Generator),调用该函数会返回该对象的一个遍历器对象。

    原生js对象不具备 Iterator 接口,无法使用上述接口,将 Generator 函数加到对象的Symbol.iterator属性上面即可使用。

    function* objGenerator() {
        let keys = Object.keys(this); // ["name", "sex", "aeg"]
        for (let key of keys) {
            yield [key, this[key]]; // [key,value]
        }
    }
    
    let xmObj = { name: 'xiaoming', sex: '男', aeg: 23 };
    
    // 将 Generator 函数加到对象的Symbol.iterator属性上面
    xmObj[Symbol.iterator] = objGenerator;
    
    for (let [key, value] of xmObj) { // 可以使用for/of遍历
        console.log(`${key}: ${value}`);
    }
    // name: xiaoming
    // sex: 男
    // aeg: 23
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    async和await

    async 函数是什么?一句话,它就是 Generator 函数的语法糖。
    async函数就是将 Generator 函数的星号(*)替换成async,将yield替换成await …
    async和await,比起星号和yield,语义更清楚了。

    async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。

    async函数返回一个 Promise 对象,可以使用then方法添加回调函数。
    async函数内部return语句返回的值,会成为then方法回调函数的参数。

    async function fn() {
        return 'hello world';
    }
    fn().then(v => console.log(v)); // "hello world"
    console.log('我先执行'); // "我先执行"
    console.log( fn() ); // Promise {<resolved>: "hello world"}
    
    async 函数有多种使用形式。
    // 函数声明
    async function foo() {}
    
    // 函数表达式
    let foo = async function () {};
    
    // 对象的方法
    let obj = { async foo() {} };
    obj.foo().then(...)
    
    // Class 的方法
    class Storage {
        constructor() {
            this.cachePromise = caches.open('avatars');
        }
        async getAvatar(name) {
            const cache = await this.cachePromise;
            return cache.match(`/avatars/${name}.jpg`);
        }
    }
    const storage = new Storage();
    storage.getAvatar('jake').then();
    
    // 箭头函数
    let foo = async () => {};
    
    // 立即执行函数
    (async function (){
        // ...
    })();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    async函数内部抛出错误,导致返回的 Promise 对象变为reject状态。抛出的错误对象会被catch方法回调函数接收到。

    async function fn() {
        throw new Error('出错了');
    }
    fn().then(
        v => console.log(v),
        e => console.log(e) // catch Error: 出错了
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    await 命令
    正常情况下,await命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值。

    async function fn() {
        return await 123;
        // 等同于
        // return 123;
    }
    fn().then( v => console.log(v) );
    // 123
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    上面代码中,await命令的参数是数值123,这时等同于return 123。

    注意,await一定要运行在async 函数内!

    当async函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

    (async function (){
        var res1 = await new Promise(function (resolve,reject){
            setTimeout(function (){
                console.log('异步任务1');
                resolve('成功1');
            },1000);
        });
        var res2 = await new Promise(function (resolve,reject){
            setTimeout(function (){
                console.log('异步任务2');
                resolve('成功2');
            },1000);
        });
        console.log(res1,res2);
        console.log('同步任务3');
        console.log('同步任务4');
    })();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    await 会等待这个 Promise 完成,并将其 resolve 的结果返回出来。

    await命令后面的 Promise 对象如果变为reject状态,则reject的参数会被catch方法的回调函数接收到。

    async function fn() {
        await Promise.reject('出错了');
    }
    fn().then(v => console.log(v)).catch(e => console.log(e))
    // 出错了
    
    • 1
    • 2
    • 3
    • 4
    • 5

    任何一个await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行。

    async function fn() {
        await Promise.reject('出错了');
        await Promise.resolve('hello world'); // 不会执行
    }
    fn().then(
        v => console.log(v),
        err => console.log(err)
    );
    // '出错了'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    await命令后面的Promise对象,运行结果可能是rejected,所以最好把await命令放在try…catch代码块中。

    async function f() {
        try {
            await Promise.reject('出错了');
        } catch(e) {
            console.log(e);
        }
        return await Promise.resolve('hello world');
    }
    f().then(v => console.log(v));
    // hello world
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    async函数返回的 Promise 对象,必须等到内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数。

    (async function (){
        var res1 = await promiseAjax({
            type: 'get',
            url: 'datas.php',
            data: 'userid=abc1001'
        });
        var res2 = await promiseAjax({
            type: 'get',
            url: 'datas.php',
            data: 'userid=abc1002'
        });
        var res3 = await promiseAjax({
            type: 'get',
            url: 'datas.php',
            data: 'userid=abc1003'
        });
        res1 = JSON.parse(res1);
        res2 = JSON.parse(res2);
        res3 = JSON.parse(res3);
        // con.innerHTML = `姓名:${res1.name},身份证:${res2.idcode},地址:${res3.address}`;
        return `姓名:${res1.name},身份证:${res2.idcode},地址:${res3.address}`;
    })().then(val=>{
        con.innerHTML = val;
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    fetch 与 axios

    fetch:号称是AJAX的替代品,是基于promise设计的。
    fetch不是ajax的进一步封装,而是原生js,代码结构比起ajax简单多了。

    axios:是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
    vue官方推荐的HTTP请求库。

  • 相关阅读:
    音视频编码
    useEffect的两个参数
    2022年全国职业院校技能大赛:网络系统管理项目-模块B--Windows样题6
    手机怎么压缩图片?通过三种压缩操作
    Day 62 数据结构(单向链表,单向循环链表,双向链表)
    YOLO 施工安全帽目标检测模型
    建模助手|说一说关于Revit的基础知识
    关于static修饰的成员方法成员成员变量的相关讨论
    【数据结构】树(六)—— 二叉平衡树(C语言版)
    深入浅出零钱兑换问题——背包问题的套壳
  • 原文地址:https://blog.csdn.net/weixin_44064067/article/details/125615981