跳至主要內容

Promise

TenSoFlow...大约 6 分钟前端Promise

Promise

第一章 简介

Promise最初被提出是在E语言中,它是基于并列或者并行处理设计的一种编程语言。Promise 是JavaScript中处理异步操作的一种方式,它代表了一个可能尚未完成操作的最终完成或者失败的结果值。Promise 对象的主要目的是提供一种更加灵活的可管理方式来处理异步代码,避免回调地狱(callback hell),使得代码更加清晰和易于维护。

第二章 创建

一个 Promise 是通过 new Promise() 构造器来创建的,构造器接收一个函数(称为执行器函数),该函数有两个参数:resolvereject

  • resolve(value):表示操作成功,value 是成功时的结果。
  • reject(error):表示操作失败,error 是失败时的错误信息。
let promise = new Promise((resolve, reject) => {
  let success = true;  // 模拟一个异步操作
  if (success) {
    resolve('操作成功');
  } else {
    reject('操作失败');
  }
});

promise.then(result => {
  console.log(result);  // 操作成功
}).catch(error => {
  console.log(error);   // 操作失败
});

第三章 常用方法

then()

then(onFulfilled, onRejected)Promise 的核心方法,用来定义操作成功时的回调函数(onFulfilled)和操作失败时的回调函数(onRejected)。

  • onFulfilled:异步操作成功时的回调函数,接收 resolve 传递的值。
  • onRejected:异步操作失败时的回调函数,接收 reject 传递的错误信息。

返回值: then() 返回一个新的 Promise,使得 then() 具有链式调用的能力。

let promise = new Promise((resolve, reject) => {
  resolve('操作成功');
});

promise.then((result) => {
  console.log(result);  // "操作成功"
}).then(() => {
  console.log('继续处理');
});

catch()

catch(onRejected) 用于指定当 Promise 被拒绝(reject)时的回调函数,它等同于 .then(null, onRejected)

返回值: catch() 返回一个新的 Promise,允许链式调用。

let promise = new Promise((resolve, reject) => {
  reject('操作失败');
});

promise.catch((error) => {
  console.log(error);  // "操作失败"
});

finally()

finally(onFinally) 用于指定无论 Promise 成功还是失败都会执行的回调函数。通常用于清理操作,如关闭文件、释放资源等。

返回值: finally() 返回一个新的 Promise,因此可以继续链式调用。

let promise = new Promise((resolve, reject) => {
  resolve('操作成功');
});

promise.then((result) => {
  console.log(result);  // "操作成功"
}).finally(() => {
  console.log('清理操作');
});

小贴士

无论 Promise 是成功还是失败,finally() 中的回调都会被执行。

all()

Promise.all(iterable) 接受一个可迭代对象(通常是一个数组),并返回一个新的 Promise,这个 Promise 会在所有输入的 Promise 都解决(fulfilled)时解决,并返回一个包含所有输入 Promise 结果的数组。

  • 如果其中有任何一个 Promise 被拒绝(rejected),则 Promise.all() 返回的 Promise 会立即被拒绝,并且拒绝的错误为第一个拒绝的 Promise 的错误。
let promise1 = new Promise((resolve, reject) => setTimeout(resolve, 1000, '结果1'));
let promise2 = new Promise((resolve, reject) => setTimeout(resolve, 2000, '结果2'));
let promise3 = new Promise((resolve, reject) => setTimeout(resolve, 1500, '结果3'));

Promise.all([promise1, promise2, promise3]).then((results) => {
  console.log(results);  // ["结果1", "结果2", "结果3"]
}).catch((error) => {
  console.log(error);
});

第四章 静态方法

Promise.resolve()

Promise.resolve(value)可以认为是new Promise()方法的快捷方式。

// 比如Promise.resolve(42)可以认为是以下代码的语法糖
new Promise(function(resolve){
    resolve(42);
});
/*
在这段代码中的resolve(42);
会让这个promise对象立即进入确定(即resolved)状态
并将42传递给后面then里所指定的onFulfilled函数中
其返回值也是一个promise对象
所以我们可以继续对其使用链式调用
*/

Promise.reject()

Promise.reject(error)是和 Promise.resolve(value)类似的静态方法,是new Promise()方法的快捷方式。

// 比如 Promise.reject(new Error("出错了")) 就是下面代码的语法糖形式。
new Promise(function(resolve, reject){
    reject(new Error("出错了"));
});
/*
这段代码的功能是调用该promise对象通过then指定的onRejected函数
并将错误(Error)对象传递给这个 onRejected 函数
它和Promise.resolve(value)的不同之处在于promise内调用的函数是reject而不是resolve
这在编写测试代码或者进行debug时,说不定会用得上
*/

第五章 async | await

asyncawait是基于Promise上的语法糖。可以让异步操作更加简洁明了。

async function test() {
  const response = await fetch("https://...");
  const json = await response.json();
  console.log(json);
}
// 使用async标记函数为异步函数
// 异步函数就是返回值为Promise对象的函数
// 上例中使用await会让后面的代码执行完才会执行下一步

注意

async只能用于函数。await只能运用在async标记的函数内并且只能用于返回值是Promise类型的。

async function test() {
  await setTimeout(() => {
    console.log("TenSoFlow");
  }, 3000)
  console.log("Hello World!")
}
test();
// 这样写照样是异步的,会先打印'Hello World!'。因为await只能作用于返回值类型是Promise类型的。

// 下面给出正确的写法,只需将setTimeout包装成一个异步函数即可
async function test() {
  await new Promise((resolve) => {
    setTimeout(() => {
      console.log("TenSoFlow");
      resolve(); // 完成时调用 resolve
    }, 3000);
  });
  console.log("Hello World!");
}
test();

注意

async作用于函数时都会显式或者隐式的返回一个Promise对象

// 隐式返回
const person = {
  name: 'John Doe',
  age: 30
}

/*
 异步函数没有显式返回Promise对象
 就会隐式返回一个Promise.resolve(undefined)对象
*/
async function setName (name) {
  person.name = name;
}

// 因为隐式的返回了Promise对象就可以链式调用then()
setName('TenSoFlow').then((resolve) => {
  console.log(resolve); // undefined
}).catch((reject) => {
  console.log(reject);
});
// 显示返回
const person = {
  name: 'John Doe',
  age: 30
}

// 此时异步函数显式的返回了Promise对象
async function setName (name) {
  person.name = name;
  /**
   * 因为async标记的方法必须返回一个Promise对象
   * 因此无论返回什么值,如果没加Promise.resolve()都会自动加上Promise.resolve()
   * 如return 1 其实是 return Promise.resolve(1)
   */
  return Promise.resolve(undefined)
}

setName('TenSoFlow').then((resolve) => {
  console.log(resolve); // undefined
}).catch((reject) => {
  console.log(reject);
});

注意

用变量去接收Promise对象则变量毫无疑问是一个Promise对象,代码是异步的。但用变量去接收一个await Promise对象则变量是Promise对象resolve的值(或是异常时抛出的reject错误),此时代码是同步的。

const person = {
  name: 'John Doe',
  age: 30
}

// 使用 await 的情况(解包 Promise)
async function setName (name) {
  console.log('1')
  const data = await new Promise(resolve => {
    setTimeout(() => {
      person.name = name
      console.log('name:', person.name) // 异步任务完成时打印
      resolve(person.name) // Promise 结果
    }, 1000)
  })
  console.log('data:', data) // 已经解包,拿到真正值
  console.log('3')
}

// 不使用 await 的情况(直接拿到 Promise 对象)
async function setAge (age) {
  console.log('A')
  const data = new Promise(resolve => {
    setTimeout(() => {
      person.age = age
      console.log('age:', person.age) // 异步任务完成时打印
      resolve(person.age) // Promise 结果
    }, 1000)
  })
  console.log('data:', data) // Promise 仍然是 pending 状态
  console.log('C')
}

setName('John')
// 输出顺序:
// 1
// name: John   (1s 后)
// data: John
// 3

setAge(25)
// 输出顺序:
// A
// data: Promise { <pending> }
// C
// age: 25      (1s 后)
评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.15.8