Promise.then()使用小结

    技术2025-12-30  7

    目录标题

    promise简介promise容器中的执行顺序resolve函数和reject函数中传递的参数如果resolve或reject中的参数是一个正常的值如果resolve或reject中的参数是promise实例对象 Promise.prototype.then()成功时的回调 和 失败时的回调函数 中的return返回值如果返回值为一个普通参数如果返回值为一个新的promise实例 成功时的回调 和 失败时的回调函数 中抛出异常Promise.prototype.catch()参考文章

    promise简介

    为了解决回调地狱嵌套,在EcmaScript6中新增了一个API:Promise。Promise是一个构造函数。Promise是一个容器,Promise本身不是异步的,但是容器内部往往存放一个异步操作。Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。resolve和reject两个形参接收的是函数,接受的函数由 JavaScript 引擎提供,不用自己部署。通过new Promise构造器创建的promise对象是有状态的,状态可能是pending(进行中),resolved(已完成,也称为fullfilled),rejected(已失败)中的一种。新创建的promise对象的状态是pending,后续可以变为resolved或rejected,状态一旦改为resolved或rejected,就不会再变了。resolve函数调用后会将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数调用后将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

    例一:

    const promise = new Promise(function(resolve, reject) { // resolve 和reject这两个形参是由 JavaScript 引擎传进来的,是两个函数 // 这里进行一些异步操作代码 if (/* 异步操作成功 */){ resolve(value); // resolve函数的作用是将这个promise对象的状态从 pending 变为 resolved。并将异步操作的结果value,作为参数传递出去。 console.log(1) } else /* 异步操作失败 */{ reject(error); // resolve函数的作用是将这个promise对象的状态从 pending 变为 rejected。并将错误传递出去。 } }); Promise实例生成以后,可以用then方法指定两个回调函数。then方法中的第一个参数,是promise对象的状态由pending变为resolved后会调用的回调函数;then方法中的第二个参数,是promise对象的状态由pending变为rejected后调用的回调函数;这两个回调函数中,rejectedCallback可选的,不一定要提供。例一中,如果异步操作成功,就会调用resolve(value),调用resolve(value),当前promise的状态由进行中变为成功,随即调用then方法中的第一个回调函数参数。我们在例一中调用resolve(value)的时候其实就可以看作是在调用then方法里传的第一个回调函数。then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行( 也就是说resolve()后面如果还有其他同步语句(如上面例子中的console.log(1) ),会先执行完这些同步语句, 然后在执行then方法中的回调函数)。 promise.then(resolvedCallback, rejectedCallback); promise.then(function(value) { // 把这个函数成为 成功时的回调函数 // 成功时的逻辑 }, function(error) { // 把这个函数成为 失败时的回调函数 // 失败时的逻辑 });

    例二:

    下面的代码中,首先利用Promise构造器创建了一个promise对象,并且调用了then方法指定了该promise对象的状态由pending变为resolved后会调用的回调函数。promise里的异步操作是一个定时操作,当计时到了后,调用了resolve()函数(也就是调用了我们在then方法中写的第一个回调函数),该函数调用后,promise对象的状态由pending变为resolved。 new Promise((resolve, reject) => { setTimeout(function () { resolve() ; }, 1000) }).then((data) => { // 因为new Promise返回的就是一个promise对象实例,所以这里可以链式操作 alert('成功的回调'); })

    promise容器中的执行顺序

    new Promise((resolve, reject) => { setTimeout(function () { console.log('时间到了') resolve('11') console.log('22') }, 1000) console.log('33') }).then((data) => { console.log(data) }) console.log('hhh') // 打印顺序: // 33 // hhh // 时间到了 // 22 // 11 promise本身不是异步的,只是内部包含了异步代码。首先启动定时器(但是不会执行定时器内部的回调函数)因为setTimeout是一个异步代码,不会影响后续代码的继续执行,所以随即执行 console.log(‘33’)new Promise部分就执行完了,然后按顺序执行 console.log(‘hhh’)当定时到了后,会执行定时器中的回调函数,依次执行 console.log(‘时间到了’) resolve(‘11’) (实际上可以看作执行then方法传过去的回调函数) console.log(‘22’)按照上面的说法应该先打印11,在打印22呀?这是为什么呢?这就是前面提到的 then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行, 也就是说console.log(22)会先打印。

    resolve函数和reject函数中传递的参数

    如果调用resolve函数和reject函数时带有参数,那么它们的参数会被传递给回调函数。reject函数的参数通常是Error对象的实例,表示抛出的错误;resolve函数的参数除了正常的值以外,还可能是另一个 Promise 实例。

    如果resolve或reject中的参数是一个正常的值

    例三:

    // 1. 创建Promise实例对象 var p1 = new Promise(function (resolve, reject) { setTimeout(function () { // 调用resolve函数后p1的状态pending->fulfilled // 然后就会调用成功的回调函数,并将这个参数1传递给回调函数 resolve(1); }, 1000); }) // 2. 通过then方法指定成功和失败时的回调函数 p1 .then(function (data) { // 成功的回调函数 (在定时器中调用resolve函数后 就会调用当前这个回调函数) console.log("data", data) }, function (err) { // 失败的回调 console.log("err", err) }) // 打印顺序 // 1s后打印'data 1' var p1 = new Promise(function (resolve, reject) { setTimeout(function () { reject(1); // 调用reject函数后,p1的状态pending->rejected }, 1000); }) p1 .then(function (data) { console.log("data", data) }, function (err) { console.log("err", err) }) // 打印顺序 // 1s后打印'err 1'

    如果resolve或reject中的参数是promise实例对象

    var p1 = new Promise(function (resolve, reject) { setTimeout(function () { resolve('1'); }, 3000); }) var p2 = new Promise(function (resolve, reject) { setTimeout(function () { resolve(p1); // resolve的参数是一个promise对象 }, 1000); }) p2 .then(function (data) { console.log('resolve执行啦') console.log(data) }, function (err) { console.log(err) }) // 打印顺序 // 3s后依次打印 'resolve执行啦' '1' 上面代码中,p1和p2都是 Promise 的实例,但是p2的resolve方法将p1作为参数。注意,这时p1的状态就会传递给p2,也就是说,p1的状态决定了p2的状态。如果p1的状态是pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是resolved或者rejected,那么p2的回调函数将会立刻执行。

    Promise.prototype.then()

    then方法会返回一个新的Promise实例。因此可以采用链式写法,即then方法后面再调用另一个then方法。采用链式的then,可以指定一组按照次序调用的回调函数。

    成功时的回调 和 失败时的回调函数 中的return返回值

    第一个回调函数完成以后,会将返回结果作为参数,传入下一级的回调函数。返回结果可能是一个参数或者一个新的promise实例(即有异步操作),这时候一个回调函数,就会等待该Promise对象的状态发生变化,才会被调用。如果then方法中的回调函数(不管是成功的回调还是失败的回调)返回了一个参数(return xxx),那么这个then方法返回的新的promise的状态会变成fulfilled(同时成功的回调函数也会被调用)。

    如果返回值为一个普通参数

    var p1 = new Promise(function (resolve, reject) { setTimeout(function () { // 执行resolve函数后p1的状态 pending->fulfilled // 然后执行p1成功时的回调函数 并传递参数 resolve('1'); }, 1000); }) var p2 = p1.then(function (data) { // p1成时的回调函数 console.log("data", data); return 'hello p2'; // 执行return语句后p2的状态pending->fulfilled 同时p2成功的回调函数会被调用 // 当前函数中 return 的结果就可以在后面的 then 中 function 接收到 }, function (err) { // p1失败时的回调函数 console.log("err", err); return 'hello p2 nihao'; }); // 当前then返回一个新的promise:p2 var p3 = p2.then(function (data) { // p2成功时的回调函数 console.log("data", data); }, function (err) { // p2失败时的回调函数 console.log("err", err); }) // 打印顺序 // 1s后打印'data 1' // 紧接着打印'data hello p2'

    写成链式调用的形式:

    var p1 = new Promise(function (resolve, reject) { setTimeout(function () { resolve('1'); }, 1000); }) p1 .then(function (data) { console.log("data", data); return 'hello p2'; }, function (err) { console.log("err", err) return 'hello p2 nihao'; }) .then(function (data) { console.log("data", data); }, function (err) { console.log("err", err); }) var p1 = new Promise(function (resolve, reject) { setTimeout(function () { reject('1'); // 执行resolve函数后p1的状态pending->rejected 失败的回调 }, 1000); }) var p2 = p1.then(function (data) { console.log("data", data); return 'hello p2'; }, function (err) { console.log("err", err) return 'hello p2 nihao'; // 执行return语句后p2的状态pending->fulfilled // 可以看出不管是成功的回调还是失败的回调中的return 但会导致当前then方法返回的promise变为成功状态 }); // 当前then返回一个新的promise:p2 p2.then(function (data) { console.log("data", data);// 这个回调会被调用 }, function (err) { console.log("err", err); }) // 打印顺序 // 1s后打印'err 1' // 紧接着打印'data hello p2 nihao' 从上面的例子可以总结出:如果then方法中返回一个参数(return xxx),那么这个then方法返回的新的promise的状态会变成fulfilled。

    如果返回值为一个新的promise实例

    var time1, time2 var p1 = new Promise(function (resolve, reject) { setTimeout(function () { // 1s后进入这里 // 执行resolve函数后p1的状态 pending->fulfilled // 然后执行p1成功时的回调函数 并传递参数 resolve('1'); }, 1000); }) var p2; p1.then (function (data) { // p1成功时的回调函数 time1 = Date.now() console.log("data", data); p2 = new Promise(function (resolve, reject) { setTimeout(function () { // 执行resolve函数后p2的状态 pending->fulfilled // 然后执行p2成功时的回调函数 并传递参数 resolve('2'); }, 3000); }); // return 一个 Promise 对象的时候,当前then()方法的返回值就是这个p2对象 return p2; }, function (err) { // p1失败时的回调函数 console.log("err", err) }) .then (function (data) { // p2成功时的回调函数 time2 = Date.now() console.log(time2-time1) console.log("data", data); }, function (err) { // p2失败时的回调函数 console.log("err", err); }) // 打印顺序 // 1s后打印'data 1' // 再过3s后依次打印'3001' 和 'data 2'

    写成链式的

    var p1 = new Promise(function (resolve, reject) { setTimeout(function () { resolve('1'); }, 1000); }) p1.then (function (data) { console.log("data", data); return new Promise(function (resolve, reject) { setTimeout(function () { resolve('2'); }, 3000); }); }, function (err) { console.log("err", err) }) .then (function (data) { console.log("data", data); }, function (err) { console.log("err", err); }) // 打印顺序 // 1s后打印'data 1' // 再过3s后依次打印'3001' 和 'data 2'

    成功时的回调 和 失败时的回调函数 中抛出异常

    如果then中抛出异常,那么这个then返回的新的promise实例的状态会被置为rejected var p1 = new Promise(function (resolve, reject) { setTimeout(function () { // p1状态pending->fulfilled // 调用p1成功时的回调函数 resolve('1'); }, 1000); }) var p2 = p1.then (function (data) { // p1成功时的回调 console.log("data", data); throw new Error('test1'); // 抛出异常后p2状态pending->rejected }, function (err) { // p1失败时的回调 console.log("err", err); throw new Error('test2'); }) p2.then (function (data) { // p2成功时的回调 console.log("data", data); }, function (err) { // p2失败时的回调 console.log("err", err); }) // 打印顺序 // 1s后打印'data 1' // 紧接着打印'err Error: test1' var p1 = new Promise(function (resolve, reject) { setTimeout(function () { // p1状态pending->rejected // 调用p1失败时的回调函数 reject('1'); }, 1000); }) var p2 = p1.then (function (data) { // p1成功时的回调 console.log("data", data); throw new Error('test1'); }, function (err) { // p1失败时的回调 console.log("err", err); throw new Error('test2'); // 抛出异常后p2状态pending->rejected }) p2.then (function (data) { console.log("data", data); }, function (err) { // p2状态变为失败后调用这个回调 console.log("err", err); }) // 打印顺序 // 1s后打印'err 1' // 紧接着打印'err Error: test2'

    Promise.prototype.catch()

    Promise.prototype.catch()方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数。 var p1 = new Promise(function (resolve, reject) { setTimeout(function () { resolve('1');// 1.调用resolve后p1的状态pending->fulfilled }, 1000); }) var p2 = p1.then (function (data) { // p1状态变为成功后调用这个回调 console.log("data", data); throw new Error('test1'); // 抛出异常后p2状态pending->rejected }, function (err) { console.log("err", err); throw new Error('test2'); }) p2.catch (function (err) { // p2状态变为失败后调用这个回调 console.log("err", err); }) // 打印顺序 // 1s后打印'data 1' // 紧接着打印'err Error: test1' var p1 = new Promise(function (resolve, reject) { setTimeout(function () { resolve('1');// 1.调用resolve后p1的状态pending->fulfilled }, 1000); }) p1.then (function (data) { // p1状态变为成功后调用这个回调 console.log("data", data); return new Promise(function (resolve, reject) { setTimeout(function () { reject('2'); // 2.调用reject后p2的状态pendging->rejected }, 3000); }); }, function (err) { console.log("err", err) }) .catch (function (err) { // p2状态变为失败后调用这个回调 console.log("err", err); }) // 打印顺序 // 1s后打印'data 1' // 紧接着打印'err 2'

    参考文章

    https://es6.ruanyifeng.com/#docs/promise https://segmentfault.com/a/1190000011652907

    Processed: 0.009, SQL: 10