javascript

JavaScript promise 常见用法

2023-05-14  本文已影响0人  暴躁程序员

promise 的出现是为了解决回调函数的两个常见问题

// 回调函数问题
问题一:回调函数多层嵌套调用(回调地狱)
问题二:每次回调的结果存在成功或失败的可能性

// 使用 promise 解决
解决问题一:promise 通过 .then 实现链式调用
解决问题二:promise 通过 .catch 统一捕获异常

1. promise对象上的 then、catch、finally 方法

  1. .then(回调函数) : resolve(e) 出口,可链式调用
  2. .catch(回调函数) :reject(e) 出口或者用于捕获程序异常
  3. .finally(回调函数):总是在最后执行
  1. 新建 promise.js
const getData = (params) => {
  return new Promise((resolve, reject) => {
    // throw new Error() // 可被 catch 捕获
    if (params?.id) {
      setTimeout(() => {
        resolve({
          errorCode: "0",
          data: {
            id: params.id,
            message: "hello promise",
          },
        });
      }, 1000);
    } else {
      setTimeout(() => {
        reject({
          errorCode: "-1",
          data: {
            message: "no params",
          },
        });
      }, 1000);
    }
  });
};

const params = { id: 1 }
getData(params)
  .then((res) => {
    console.log('res',res); 
  })
  .catch((err) => {
    console.log('err',err); 
  })
  .finally(() => {
    console.log("我是 finally 总是最后执行");
  });
  1. 终端执行
node promise.js 
  1. 结果
// 2s 后
res { errorCode: '0', data: { id: 1, message: 'hello promise' } }
我是 finally 总是最后执行

2. promise 对象简化写法,Promise.resolve()、Promise.reject()

  1. 新建 promise.js
const resolve = Promise.resolve("hello Promise.resolve");
resolve.then((res) => {
  console.log(res);
});
const reject = Promise.reject("hello Promise.reject");
reject.catch((err) => {
  console.log(err);
});
  1. 终端执行
node promise.js 
  1. 结果
hello Promise.resolve
hello Promise.reject

3. 等所有 promise 异步执行完毕统一返回结果(短路),Promise.all([p1,p2,p3])

  1. Promise.all() 接受一个由promise对象组成的数组:如果传入函数返回的promise对象,需要传入函数立即执行后的结果
  2. 特点:短路,必须所有的都是 resolve 否则才返回所有结果,否则发现第一个 reject 就直接返回那个 reject的结果
  3. 获取结果(全部 resolve):按照 [fn1,fn2,fn3] 传参时的顺序,以数组的方式返回结果(不是按响应的时间顺序返回结果)
  1. 新建 promise.js
console.log('start');
const p1 = (() => {
  return new Promise((resolve, reject) => {
    console.log("p1");
    const status = true;
    if (status) {
      setTimeout(() => {
        resolve("p1:成功");
      }, 1000);
    } else {
      setTimeout(() => {
        reject("p1:失败");
      }, 1000);
    }
  });
})();

const p2 = new Promise((resolve, reject) => {
  console.log('p2');

  const status = true;
  if (status) {
    setTimeout(() => {
      resolve("p2:成功");
    }, 3000);
  } else {
    setTimeout(() => {
      reject("p2:失败");
    }, 1000);
  }
});

const p3 = new Promise((resolve, reject) => {
  console.log('p3');

  const status = true;
  if (status) {
    setTimeout(() => {
      resolve("p3:成功");
    }, 2000);
  } else {
    setTimeout(() => {
      reject("p3:失败");
    }, 2000);
  }
});

Promise.all([p1, p2, p3])
  .then((res) => {
    console.log('res',res); 
  })
  .catch((err) => {
    console.log('err',err); 
  });
  1. 终端执行
node promise.js 
  1. 结果
// 立即打印
start
p1
p2
p3
// 3s 后
res [ 'p1:成功', 'p2:成功', 'p3:成功' ]

4. 等所有 promise 异步执行完毕统一返回结果,Promise.allSettled([p1,p2,p3])

  1. Promise.allSettled() 接受一个由promise对象组成的数组:如果传入函数返回的promise对象,需要传入函数立即执行后的结果
  2. 特点:解决 Promise.all 短路问题
  3. 获取结果:此方法解决了 Promise.all() 短路的问题,不管是 resolve 还是 reject,都会按照 [fn1,fn2,fn3] 传参时的顺序,以数组的方式将状态和数据放入对象中统一返回
  1. 新建 promise.js
console.log('start');
const p1 = (() => {
  return new Promise((resolve, reject) => {
    console.log("p1");
    const status = true;
    if (status) {
      setTimeout(() => {
        resolve("p1:成功");
      }, 1000);
    } else {
      setTimeout(() => {
        reject("p1:失败");
      }, 1000);
    }
  });
})();

const p2 = new Promise((resolve, reject) => {
  console.log('p2');

  const status = true;
  if (status) {
    setTimeout(() => {
      resolve("p2:成功");
    }, 3000);
  } else {
    setTimeout(() => {
      reject("p2:失败");
    }, 1000);
  }
});

const p3 = new Promise((resolve, reject) => {
  console.log('p3');

  const status = false;
  if (status) {
    setTimeout(() => {
      resolve("p3:成功");
    }, 2000);
  } else {
    setTimeout(() => {
      reject("p3:失败");
    }, 2000);
  }
});

Promise.allSettled([p1, p2, p3])
  .then((res) => {
    console.log('res',res); 
  })
  .catch((err) => {
    console.log('err',err); 
  });
  1. 终端执行
node promise.js 
  1. 结果
// 立即打印
start
p1
p2
p3
// 3s 后
res [
  { status: 'fulfilled', value: 'p1:成功' },
  { status: 'fulfilled', value: 'p2:成功' },
  { status: 'rejected', reason: 'p3:失败' }
]

5. 不等所有 promise 异步执行完毕,只是返回响应最快的 promise 结果,Promise.race([p1,p2,p3])

  1. Promise.race() 接受一个由promise对象组成的数组:如果传入函数返回的promise对象,需要传入函数立即执行后的结果
  2. 获取结果:不管是 resolve 还是 reject,只是返回响应最快的 promise 结果
  1. 新建 promise.js
console.log('start');
const p1 = (() => {
  return new Promise((resolve, reject) => {
    console.log("p1");
    const status = true;
    if (status) {
      setTimeout(() => {
        resolve("p1:成功");
      }, 1000);
    } else {
      setTimeout(() => {
        reject("p1:失败");
      }, 1000);
    }
  });
})();

const p2 = new Promise((resolve, reject) => {
  console.log('p2');

  const status = true;
  if (status) {
    setTimeout(() => {
      resolve("p2:成功");
    }, 3000);
  } else {
    setTimeout(() => {
      reject("p2:失败");
    }, 1000);
  }
});

const p3 = new Promise((resolve, reject) => {
  console.log('p3');

  const status = false;
  if (status) {
    setTimeout(() => {
      resolve("p3:成功");
    }, 2000);
  } else {
    setTimeout(() => {
      reject("p3:失败");
    }, 2000);
  }
});

Promise.race([p1, p2, p3])
  .then((res) => {
    console.log('res',res); 
  })
  .catch((err) => {
    console.log('err',err); 
  });
  1. 终端执行
node promise.js 
  1. 结果
// 立即打印
start
p1
p2
p3
// 3s 后
res p1:成功
上一篇 下一篇

猜你喜欢

热点阅读