当前位置: 首页 > article >正文

JS异步进化与Promise

JavaScript 是单线程的,但它并不是无法处理异步操作。相反,JavaScript 的单线程特性和其事件循环机制使得它在处理异步任务方面非常高效

回调函数(Callback Functions)

一开始JS使用回调的形式来处理异步的结果,但是异步的弊端很大

例如:无法更好的处理错误,无法追溯数据来源,无法使用同步,回调地狱等问题

console.log("开始");

setTimeout(() => {
  console.log("异步操作完成");
}, 1000);

console.log("结束");

//result

开始
结束
异步操作完成

回调地狱是最头疼的,所以就需要改变他

setTimeout(() => {
    console.log("第一步完成");
    setTimeout(() => {
        console.log("第二步完成");
        setTimeout(() => {
            console.log("第三步完成");
        }, 1000);
    }, 1000);
}, 1000);

Promise(Promise A+ 规范)

所谓Promise 就是一个承诺

Promise的状态

  • Pending(待定): 初始状态,既不是成功也不是失败
  • resolved / fullfilled (已完成): 表示操作成功完成
  • Rejected(已失败): 表示操作失败
//初始状态
let promise = new Promise((resolve, reject) => {
  // promise 初始状态是 pending
});


//Fulfilled
let promise = new Promise((resolve, reject) => {
  resolve('成功的结果');
});

promise.then((value) => {
  console.log(value); // 输出: 成功的结果
});


//Rejected
let promise = new Promise((resolve, reject) => {
  reject('失败的原因');
});

promise.catch((reason) => {
  console.log(reason); // 输出: 失败的原因
});

切记你从一个状态改变到另一个状态后就无法再改变了

Promise的存储

Promise 的状态可以从 pending 变为 fulfilledrejected,但一旦变为 fulfilledrejected,就不能再变为其他状态。这种状态的不可变性确保了 Promise 的一致性和可靠性,每一种状态都会有定义的返回的值

当执行函数调用 resolve 时,Promise 的状态从 pending 变为 fulfilled

resolve 可以接受一个参数,作为 Promise 成功的值, PromiseResult变为存储的数据 , 调用then的第一个回调函数来返回数据

let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('成功的结果');
  }, 1000);
});

promise.then((value) => {
  console.log(value); // 1秒后输出: 成功的结果
});

当执行函数调用 reject 时,Promise 的状态从 pending 变为 rejected

reject 可以接受一个参数,作为 Promise 失败的原因, PromiseResult变为存储的数据 或 异常对象

let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('失败的原因');
  }, 1000);
});

promise.catch((reason) => {
  console.log(reason); // 1秒后输出: 失败的原因
});

Promise实例方法

.then

  • 用于指定当 Promise 成功时的回调函数
  • 它接受两个参数,第一个是成功时的回调函数onFulfilled
  • 第二个是失败时的回调函数onRejected(可选)
  • 返回一个新的 Promise 对象
const p1 = new Promise((resolve, reject) => {
  resolve("成功!");
  // 或
  // reject(new Error("错误!"));
});

p1.then(
  (value) => {
    console.log(value); // 成功!
  },
  (reason) => {
    console.error(reason); // 错误! //但是这个回调不常用,建议使用.catch
  },
);

.catch

  • 用于指定当 Promise 失败时的回调函数onRejected
  • 抛出错误也可以使状态变为Rejected
  • Promise已对现,则catch不会被调用
  • 返回一个新的 Promise 对象
let promise = new Promise((resolve, reject) => {
  reject('失败');
});

promise.catch(function(reason) {
  console.log(reason); // 失败
});

.finally

  • 用于指定不论 Promise 最终状态如何都会执行的回调函数
  • 返回一个新的 Promise 对象
function checkMail() {
  return new Promise((resolve, reject) => {
    if (Math.random() > 0.5) {
      resolve('Mail has arrived');
    } else {
      reject(new Error('Failed to arrive'));
    }
  });
}

checkMail()
  .then((mail) => {
    console.log(mail);
  })
  .catch((err) => {
    console.error(err);
  })
  .finally(() => {
    console.log('Experiment completed');
  });

 Promise静态方法

.resolve

  • 返回一个成功的以给定值解析后的 Promise 对象
  • 如果传入的参数是一个 Promise 对象,则参数的结果直接影响返回值
  • 如果不是Promise 对象,那么就直接返会成功的Promise 对象
  • 该函数将嵌套的类 Promise 对象(例如,一个将被兑现为另一个 Promise 对象的 Promise 对象)展平,转化为单个 Promise 对象,其兑现值为一个非 thenable
Promise.resolve(42).then(function(value) {
  console.log(value); // 42 //resolve
});

let p1 = Promise.resolve(521);
console.log(p1)  //resolve

.reject

  • 返回一个失败的 Promise
  • 无论参数的形式,结果都是失败的,哪怕是成功的Promise
function resolved(result) {
  console.log('Resolved');
}

function rejected(result) {
  console.error(result);
}

Promise.reject(new Error('fail')).then(resolved, rejected);
// Expected output: Error: fail

.all

  • 接受一个包含多个 Promise 的数组,返回的也是数组
  • 返回一个新的 Promise, 当所有传入的 Promise 都成功完成(fulfilled)时完成
  • 或者只要有一个 Promise 失败(rejected)时就失败并带有第一个被拒绝的原因
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then((values) => {
  console.log(values);
});
// Expected output: Array [3, 42, "foo"]

.race

  • 接受一个包含多个 Promise 的数组
  • 返回一个新的 Promise,谁先执行完毕,谁的结果就决定race的结果
const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, 'one');
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'two');
});

Promise.race([promise1, promise2]).then((value) => {
  console.log(value);
  // Both resolve, but promise2 is faster
});
// Expected output: "two"

.any

  • 接受一个可迭代对象
  • 返回一个新的 Promise只要传入的 Promise 中有一个成功,并返回第一个兑现的值
  • 如果所有的 Promise 都失败,则返回一个失败的 Promise,并附带一AggregateError 错误
const promise1 = Promise.reject(0);
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, 'quick'));
const promise3 = new Promise((resolve) => setTimeout(resolve, 500, 'slow'));

const promises = [promise1, promise2, promise3];

Promise.any(promises).then((value) => console.log(value));

// Expected output: "quick"

关于Promise的详细内容还有许多,本文仅做简略描述,请谅解

async与await (ES8/ES2017)

他的作用就是使你的promise代码看起来像同步一样

async

  • 用于声明一个异步函数
  • 异步函数默认返回一个 Promise 对象
  • 如果函数内部返回的是一个非 Promise 的值,它会被自动封装成 Promise.resolve(value)

await 

  • 用于等待一个异步操作(即 Promise)的完成
  • await 必须在 async 函数内部使用
  • 它会暂停代码执行,直到 Promise 的结果返回(成功或失败)

 传统写法

function fetchData() {
    return new Promise((resolve) => {
        setTimeout(() => resolve("数据加载完成"), 1000);
    });
}

fetchData()
    .then((result) => {
        console.log(result);
        return "下一步操作";
    })
    .then((nextResult) => {
        console.log(nextResult);
    })
    .catch((err) => {
        console.error(err);
    });

新式写法

async function fetchData() {
    return new Promise((resolve) => {
        setTimeout(() => resolve("数据加载完成"), 1000);
    });
}

async function run() {
    try {
        const result = await fetchData();
        console.log(result);

        const nextResult = "下一步操作";
        console.log(nextResult);
    } catch (err) {
        console.error(err);
    }
}

run();


http://www.kler.cn/a/414146.html

相关文章:

  • 六大排序算法:插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序
  • scala的守卫语句格式
  • Vue.js 中的事件监听与事件修饰符
  • git flow 相关知识 git rebase 与 merge 合并差异比较
  • TortoiseSVN 基本操作 - 下载/上传/更新/repo查看
  • PAT甲级-1064 Complete Binary Search Tree
  • 记录一次在生产环境中更换 SSL 证书的操作
  • Qt creator设置程序图标
  • 【docker】docker的起源与容器的由来、docker容器的隔离机制
  • Python标识符命名规则
  • 介绍下你们电商搜索的整体Java技术架构?
  • 算法基础 - 二分迭代法求解非线性方程
  • 大数据新视界 -- 大数据大厂之 Hive 数据安全:权限管理体系的深度解读(上)(15/ 30)
  • CatVton升级版?CatVton-Flux:AI虚拟试衣方案新选择。
  • python辅助notepad
  • Spring Boot框架下的英语学习应用开发
  • 关于Vscode配置Unity环境时的一些报错问题(持续更新)
  • 鸿蒙Next星河版基础代码
  • 打造双层环形图:基础与高级渐变效果的应用
  • Could not load library libnvrtc.so.11.2. Error: libnvrtc.so.11.2