首页系统综合问题一首歌带你搞懂Promise

一首歌带你搞懂Promise

时间2023-01-09 19:15:27发布分享专员分类系统综合问题浏览249

今天小编给各位分享promise的知识,文中也会对其通过一首歌带你搞懂Promise和郑容和《promise》歌曲中文翻译等多篇文章进行知识讲解,如果文章内容对您有帮助,别忘了关注本站,现在进入正文!

内容导航:

  • 一首歌带你搞懂Promise
  • 郑容和《promise》歌曲中文翻译
  • 一首歌歌词里面好几个promise,女生唱的
  • 找一首欧美歌曲 只记得歌词里一个单词promise 是个男歌手
  • 一、一首歌带你搞懂Promise

    Promise简介

    Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。(摘自<ECMAScript 6 入门>),但是对于Promise的创建和执行流程,其实有很多人初学时,容易走入误区。

    今天就以一首歌来带大家学习Promise。

    Promise创建

    Promise翻译过来的意思就是"承诺",其实Promise的创建本质就是一个许下承诺的过程,想到这我的脑海中不由得浮现了一首经典老歌,海鸣威 《你的承诺》。

    歌中相知相恋的两个人,奈何情深缘浅,终于还是分开,许下了“不为彼此难过, 过各自的生活"这样的承诺。但是随后歌曲又以"Oh baby 你答应我的我都记得 ,但是你却忘了你的承诺 ,不是说好彼此都不再联络, 谁都别再犯错",暗示承诺的状态发生改变。

    由此不难想象以下两种情况:

    遵守承诺

    违背承诺

    同样,JS中的Promise的创建也是许下代码承诺的一种方式,它默认也包含三种状态:

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

    那么如何许下JS中的承诺呢:

    var p = new Promise(function(){ // 回调函数})

    Promise中接收一个回调函数(简单说就是一个容器),传入某个未来才会结束的事件(通常是一个异步操作)的结果;此时打印,你会得到一个Promise实例(实例化对象),展开之后默认显示:

    Promise {<pending>} [[Prototype]]: Promise, [[PromiseState]]: "pending", [[PromiseResult]]: undefined,

    此时我们会看到

    [[PromiseState]]用于存储Promise实例(当前承诺)的状态 ,默认显示pending ;[[PromiseResult]]用于表示Promise实例中存储的数据 , 默认显示undefined;[[Prototype]]表示原型 以后再做讲解

    但是有人就会问了,既然有三种状态,而默认是pending(进行中)状态,那么我们如何将当前Promise实例的状态改为另外两种:

    这就不得不提到Promise的第一特征了:

    对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。

    可以理解为,状态并不是自行改变的,而是由异步(同步也可以)的结果决定了.。

    所以Promise在创建过程中,传入的回调函数接收了改变状态的两个方法 ,resolve,reject作为形式参数传入.

    var p = new Promise(function(resolve,reject){//形式参数 // 回调函数})

    resolve() 将Promise实例的状态 由pending(进行中) 改为 fulfilled(已成功)

    reject() 将Promise实例的状态 由pending(进行中) 改为rejected(已失败)

    而且resolve() reject() 方法在调用时 还可以接收一个参数,作为数据传入,存储到Promise实例中。

    同步代码展示:

    var p = new Promise(function(resolve,reject){//形式参数 // 回调函数 resolve(111)})console.log(p)结果:Promise {<fulfilled>: 111}    [[Prototype]]: Promise    [[PromiseState]]: "fulfilled"   // 已成功    [[PromiseResult]]: 111          // 存储数据    var p = new Promise(function (resolve, reject) {//形式参数    // 回调函数    reject(222)})Promise {<rejected>: 111} [[Prototype]]: Promise [[PromiseState]]: "rejected"   // 已失败 [[PromiseResult]]: 222         // 存储数据  Uncaught (in promise) 111         // 报错 (可以不用理会  后面会被then() / catch() 方法捕获)

    resolve() 和 reject() 方法,在同步代码中调用,会立即改变Promise实例的状态。

    异步代码展示:

    var p = new Promise(function (resolve, reject) {//形式参数    setTimeout(function () {        resolve(111);        console.log("line 24:", p);    }, 2000)})console.log("line 27:", p);结果依次为:line 27: Promise {<pending>}line 24: Promise {<fulfilled>: 111}-------------------------------------两次代码请分开执行-------------------------------------------------var p = new Promise(function (resolve, reject) {//形式参数    setTimeout(function () {        reject(111);        console.log("line 24:", p);    }, 2000)})console.log("line 27:", p);结果依次为:line 27: Promise {<pending>}...2s后line 24: Promise {<rejected>: 111}报错: 2.html:60 Uncaught (in promise) 111    (可以不用理会  后面会被then() / catch() 方法捕获)

    resolv e() 和 reject() 方法,在异步代码中调用:由于JS是单线程,会优先在主线程执行同步代码,异步代码会放到任务队列中,所以在页面加载时,,Promise实例为pending(进行中)状态,等待主线程执行完毕,任务队列通知主线程,异步任务可以执行了,该任务才会进入主线程执行。

    此时setTimeout中的回调函数被调用,执行了resolve() 或 reject() 方法, Promise实例会随之改变状态,并存储传入的数据。

    那么resolve() reject() 方法,可以重复调用么?

    这就要讲到Promise的第二大特征:一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型) 注意,为了行文方便,本章后面的resolved统一只指fulfilled状态,不包含rejected状态。

    由此可见Promise本质,就是一个状态机,当该Promise对象创建出来之后,其状态就是pending(进行中),然后通过程序来控制到底是执行已完成,还是执行已失败。

    因为Promise处理的是异步任务,所以我们还得对Promise做监听,当Promise的状态发生变化时,我们要执行相应的函数(then catch finally)。

    Promise的动态方法

    所谓Promise动态方法,即将封装的方法存储在Promise的原型对象(prototype)上,供所有通过构造函数创建的实例化对象使用。

    Promise.prototype.then()

    Promise 实例具有then方法,它的作用是为 Promise 实例添加状态改变时的回调函数,前面说过 Promise实例的状态可以从pending(进行中) 变为 fulfilled(已成功)或rejected(已失败),所以then方法中接收两个回调函数(它们都是可选的)。

    p.then(resolveHandler,rejectHandler)

    resolveHandler 第一参数,用于指定Promise实例,由pending(进行中) 变为 fulfilled(已成功)时执行的回调函数。

    rejectHandler 第二参数,用于指定Promise实例,由pending(进行中) 变为 rejected(已失败)时执行的回调函数。

    可以理解为 then()方法中的两个回调函数,提前规定好了状态改变时需要执行的内容,等待以后Promise实例的状态之后再执行对应的回调函数 (本质还是回调函数,要用魔法打败魔法)。

    注意:resolveHandler rejectHandler 中可以传入一个形式参数 接收Promise实例中存储数据。

    // 等待两秒后 随机一个0-1的数,如果 num>=0.5 就变为fulfilled,否则变为rejectedvar p = new Promise(function (resolve, reject) {//形式参数        setTimeout(function () {            var num = Math.random();            if (num >= 0.5) {                resolve(111)            } else {                reject(2222);            }            console.log("line 24:", p);        }, 2000)    })console.log("line 27:", p);p.then(function (arg) { console.log("line 50", arg);}, function (arg) { console.log("line 52", arg);})情况1: (num>=0.5)      line 27: Promise {<pending>}    ...2秒后    line 24: Promise {<fulfilled>: 111}    line 50 111    情况2: (num<0.5)  line 27: Promise {<pending>} ...2秒后    2.html:81 line 24: Promise {<rejected>: 2222}    2.html:89 line 52 2222

    解析:在异步代码中调用: 由于JS是单线程,会优先在主线程执行同步代码,异步代码会放到任务队列中,所以

    Promise创建完毕,Promise实例为pending(进行中)状态;调用 then()方法,传入两个回调函数,提前规定好了状态改变时需要执行的内容,等待以后Promise实例的状态之后再执行对应的回调函数;等待主线程执行完毕,任务队列通知主线程,异步任务可以执行了,该任务才会进入主线程执行。=> 随机一个0-1的随机数,根据结果改变Promise实例的状态 ,存储传入的数据 => 执行then方法中对应的回调函数。

    还有一个有趣的地方:then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。

        var p = new Promise(function (resolve, reject) {//形式参数        setTimeout(function () {            resolve(1);        }, 2000);    })    p.then(function (num) {        console.log("line 64:", num);        return 2;    }).then(function (num) {        console.log("line 67:", num);        return 2;    })    结果:    line 64: 1    line 67: 2

    上面的代码使用then方法,依次指定了两个回调函数。第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数。当然这里有一个前提,那就是Promise实例的状态为已成功且代码执行过程中不出错的情况下。万一出错的话,那我们就可以使用then()方法的第二个回调函数或者catch()方法捕获错误。

    Promise.prototype.catch()

    catch()方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数。

     function readText(url) {        var p = new Promise(function (resolve, reject) {            $.ajax({                type: "get",                url: url,                success: function (text) {                    resolve(text);                },                error:function(err){                 reject(err);                }            })        })        return p; // {pending}    }    readText("../data/1.txt").then(res => {        console.log("line 93", res)    }).catch(err => {        console.log(err);    })

    上面代码中,readText()方法返回一个 Promise 对象,如果该对象状态变为resolved,则会调用then()方法指定的回调函数;如果异步操作抛出错误,状态就会变为rejected,就会调用catch()方法指定的回调函数,处理这个错误。另外,then()方法指定的回调函数,如果运行中抛出错误,也会被catch()方法捕获。

    then和catch的链式操作

    then()和catch()配合使用,实现的链式操作效果更佳。

        var p = new Promise(function (resolve, reject) {        setTimeout(function () {            resolve(1);        }, 2000);    })    console.log("line 21", p);    p.then(function (num) {        console.log("line 23:", num);        return 2;    }).then(function (num) {        console.log("line 25:", num);    }).then(function (num) {        console.log("line 28:", num);    }).catch(function (err) {        console.log(err);    })    结果:    line 21 Promise {<pending>}    ...等待2s后    line 23: 1    line 25: 2    line 28: 3

    上面的代码使用then catch方法进行链式调用,依次指定了三个then()的回调函数以及一个catch()的回调函数。第一个回调函数完成以后,会将返回结果作为参数,传入第二个回调函数,同样第二个回调函数完成后,会将返回结果作为参数,传入第三个回调函数,以此类推。当然这里同样也有一个前提,那就是Promise实例的状态为已成功且代码执行过程中不出错的情况下。万一出错的话,那catch()方法刚好捕获链式操作过程中出现的错误。

    如果then方法中回调函数的返回值也是一个Promise实例;

    function readText(url) {        var p = new Promise(function (resolve, reject) {            $.ajax({                type: "get",                url: url,                success: function (text) {                    resolve(text);                },                error: function (err) {                    reject(err);                }            })        })        return p; // {pending}    }    // ajax恐怖回调的解决方式1:    // T = T1 + T2 + T3   (时间)    var str = "";    readText("../data/1.txt").then(txt => {        console.log("line 36", txt);        str += txt;        return readText("../data/2.txt");    }).then(txt => {        console.log("line 40", txt);        str += txt;        return readText("../data/3.txt");    }).then(txt => {        console.log("line 44", txt);        str += txt;        return str;    }).then(txt => {        console.log("line 48", txt);    }).catch(err => {        console.log("失败:", err);    })    结果:    line 36 11111  line 40 22222 line 44 33333 line 48 111112222233333  

    上面代码中,第一个then方法指定的回调函数,返回的是另一个Promise对象。这时,第二个then方法指定的回调函数,就会等待这个新的Promise对象状态发生变化。如果变为resolved,继续链式调用后面then方法中指定的回调函数,如果状态变为rejected,就会被catch方法捕获。

    注意:Promise 实例的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。也就是说,错误总是会被下一个catch语句捕获。

    Promise的静态方法

    所谓Promise静态方法,即将封装的方法存储在构造函数Promise上,由构造函数自身调用。

    Promise.all

    Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

    const p = Promise.all([p1, p2, p3]);

    相较于then方法的链式操作,Promise.all()更注重并发,即依次按顺序发送多个请求,等待所有的请求均有结果之后,对应请求顺序将数据依次存放到数组中返回。

    模拟封装(简易版)  Promise.myAll = function (list) {        return new Promise(function (resolve, reject) {  // 返回一个新的Promise实例            var arr = [];            for (let i = 0; i < list.length; i++) {                let p = list[i];// 每一个Promise实例(如果传入的数据非Promise实例 会通过Promise.resolve转化)                                // 提前规定好每一个实例 成功和失败时执行的内容  => 请求有结果之后会执行                p.then(res => {  //等待异步操作有结果之后 对应下标放到数组中                    arr[i] = res;                                    if (arr.length === list.length) { // 所有的请求全都成功 => (也是一个异步操作)                        resolve(arr);                    }                }).catch(err => {    //只要有一个失败 就走catch                      console.log(err);                    reject(err);                   })            }        }) }  const p = Promise.myAll([p1, p2, p3]);   

    通过以上代码可以发现: (摘自ECMAScript 6 入门)

    Promise.all()方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例,如果不是,就会先调用下面讲到的Promise.resolve方法,将参数转为 Promise 实例,再进一步处理。另外,Promise.all()方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。

    p的状态由p1、p2、p3决定,分成两种情况。

    (1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。

    (2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

    Promise.race

    Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

    const p = Promise.race([p1, p2, p3]);

    相较于Promise.all方法, Promise.race方法更侧重状态改变的速度。

    模拟封装(简易版) Promise.myRace = function (list) {    return new Promise(function (resolve, reject) {  // 返回一个新的Promise实例         for (let i = 0; i < list.length; i++) {             let p = list[i];// 每一个Promise实例 (如果传入的数据非Promise实例 会通过Promise.resolve转化)              // 提前规定好每一个实例 成功和失败时执行的内容  => 请求有结果之后会执行             p.then(res => {  //等待异步操作有结果之后 对应下标放到数组中              resolve(res);             }).catch(err => {              reject(err);             })       }    })}const p = Promise.myRace([p1, p2, p3]);

    通过以上代码可以发现: (摘自ECMAScript 6 入门)

    只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

    Promise.allSettled

    Promise.allSettled()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

    const p = Promise.allSettled([p1, p2, p3]);

    相较于Promise.all方法,Promise.allSettled跟注重于不管每一个Promise实例是成功还是失败,都会将结果依次按请求顺序放到数组中。

    模拟封装(简易版) Promise.myAllSettled = function (list) {         return new Promise(function (resolve, reject) {  // 返回一个新的Promise实例             var arr = [];             for (let i = 0; i < list.length; i++) {                 let p = list[i];// 每一个Promise实例   (如果传入的数据非Promise实例 会通过Promise.resolve转化)                  // 提前规定好每一个实例 成功和失败时执行的内容  => 请求有结果之后会执行                 p.then(res => {  //等待异步操作有结果之后 对应下标放到数组中                     var obj = { status: "fulfilled", value: txt };                     arr[i] = obj;                     if (arr.length === list.length) { // 请求全都成功 => arr(异步)                         resolve(arr);                     }                 }).catch(err => {                     var obj = { status: "rejected", reason: err };                     arr[i] = obj;                     if (arr.length === list.length) { // 请求全都成功 => arr(异步)                         resolve(arr);                     }                 })             }         })     }     const p =  Promise.myAllSettled([p1, p2, p3])

    值得注意的地方时,在将数据放到数组的过程中,传入的Promise实例的状态不同,放置的结果稍有不同(数组中的每个成员是一个对象,对象的格式是固定的)。

    // 异步操作成功时{status: 'fulfilled', value: value}// 异步操作失败时{status: 'rejected', reason: reason}

    成员对象的status属性的值只可能是字符串fulfilled或字符串rejected,用来区分异步操作是成功还是失败。如果是成功(fulfilled),对象会有value属性,如果是失败(rejected),会有reason属性,对应两种状态时前面异步操作的返回值。

    总结

    有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。

    Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

    升级用法 async await

    ES2017 标准引入了 async 函数,使得异步操作变得更加方便。

    async 函数是什么?一句话,它就是 Generator 函数的语法糖。

    基本用法

     async function fn() {        var str = "";        var text = await readText("../data/1.txt"); // Promise实例        console.log("line 29:",text);        str += text;        var text = await readText("../data/2.txt"); // Promise实例        console.log("line 33:",text);        str += text;        var text = await readText("../data/3.txt"); // Promise实例        console.log("line 37:",text);        str += text;        return str;    }        fn().then(res=>{     console.log("line 44:",res)    }).catch(err=>{     console.log("line 46:",err)    })        结果:    line 29: 11111 line 33: 22222 line 37: 33333 line 44: 111112222233333   

    async函数的返回值也是一个Promise实例,在async函数执行的过程中,一旦遇到await就会先返回pending(进行中)状态的Promise实例,等待异步操作有结果之后,继续执行await之后的语句,依次类推,语句全部执行完毕且无错误的情况下,则返回的Promise实例会变为已成功,否则会变为已失败。

    你学会了么?文章底部留言告诉我喲。

    一、郑容和《promise》歌曲中文翻译

    I will promise you 我的双眼只为望着你而存在
    I will promise you 我的双手只为抱住你而存在
    从早到晚我只想念你一个
    我爱你 这句话请别忘记 I Love you Forever

    炎热的夏天请让我成为你的树荫
    下雨时请让我成为你的雨伞
    当你走累时请让我成为你的小凳子
    快乐时与我一同欢笑将快乐变成两倍
    流泪时我愿成为手帕为你擦拭

    I will promise you 我的双眼只为望着你而存在
    I will promise you 我的双手只为抱住你而存在
    从早到晚我只想念你一个
    我爱你 这句话请别忘记 I Love you Forever

    我们之间就像Coffee and Doughnut
    给我带来快乐的你对我来说是如此特别
    一天一天的缺少Energy那就Emergency
    是你的香气吹过带给我生命
    每天我都会将对你的爱一一收集
    等到我们在一起的那一刻全部传达给你

    I will promise you 无论在哪我都会记得你
    I will promise you 无论做什么我都会想念你
    我会永远抱着铭记着你的心而活
    我爱你 这句话请记住 I love Forever

    Yes A.N.GELL why here
    I will promise Just do it Girl
    相爱的时候还需要说什么
    我会用那蹦蹦跳的左心房来回答

    One step Two step Three and Four
    慢慢的走近你
    我不会说你等我这些话
    I will take you

    I will promise you 我的双眼只为望着你而存在
    I will promise you 我的双手只为抱住你而存在
    从早到晚我只想念你一个
    我爱你 这句话请别忘记 I Love you Forever

    二、一首歌歌词里面好几个promise,女生唱的

    Leona Lewis - Footprints In The Sand (本人也很喜欢此歌~~)

    歌词:
    You walked with me
    Footprints in the sand
    And helped me understand
    Where I’m going
    You walked with me
    When I was all alone
    With so much I no along the way
    Then I heard you say
    I promise you
    I’m always there
    When your heart is filled
    with sorrow and despair
    I’ll carry you
    When you need a friend
    You’ll find my footprints
    in the sand
    I see my life
    Flash across the sky
    So many times have I
    Been so afraid ooh
    And just when I
    Have thought I’ve lost my way
    You give me strength to carry on
    That’s when I heard you say
    I promise you
    I’m always there
    When your heart is filled
    with sorrow and despair
    I’ll carry you
    When you need a friend
    You’ll find my footprints
    in the sand
    When I’m weary
    Well I no you’ll be there
    And I can feel you
    When you say
    I promise you
    I’m always there
    When your heart is full of
    sadness and despair
    I’ll carry you
    When you need a friend
    You’ll find my footprints
    in the sand
    oooooo mmmmmmmm
    When your heart is filled
    with sorrow and despair
    I’ll carry you
    When you need a friend
    You’ll find my footprints
    in the sand
    oooooo mmmmmmmm

    三、找一首欧美歌曲 只记得歌词里一个单词promise 是个男歌手

    The Fray 的Never Say Never.
    Some things we don't talk about
    better do without
    just hold a
    smile
    we're falling in and out of love
    the same damn
    problem

    together all the while
    you can never say never
    when we
    don't know why
    time and time again
    younger now then we were
    before

    don't let me go,
    don't let me go,
    don't let me go,
    don't
    let me go,
    don't let me go,
    don't let me go

    picture you're the
    queen of everything
    as far as the i can see
    under your command
    i will
    be your gaurdening
    when all is crumbling
    steady your hand

    you can
    never say never
    when we don't know why
    time and time again
    younger now
    then we were before

    don't let me go,
    don't let me go,
    don't let me
    go,
    don't let me go,
    don't let me go,
    don't let me go

    we're
    falling apart
    and coming together again and again
    we're coming
    apart
    but we hold it together
    hold it together, together
    again

    don't let me go,
    don't let me go,
    don't let me go,
    don't
    let me go,
    don't let me go,
    don't let me go.

    don't let me
    go,
    don't let me go,
    don't let me go,
    don't let me go,
    don't let me
    go,

    希望能提供帮助,谢谢!
    don't let me go.

    关于promise的问题,通过《一首歌歌词里面好几个promise,女生唱的》、《找一首欧美歌曲 只记得歌词里一个单词promise 是个男歌手》等文章的解答希望已经帮助到您了!如您想了解更多关于promise的相关信息,请到本站进行查找!

    爱资源吧版权声明:以上文中内容来自网络,如有侵权请联系删除,谢谢。

    promise
    每日一词∣网络文明internet civilization 免费好用的PDF编辑器,推荐一下?