약속이란 무엇입니까? 약속 소개
이 기사에서는 Promise가 무엇인지 설명합니다. Promise의 소개에는 참고할만한 가치가 있습니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.
사실 저는 오랫동안 Promise의 사용법에 대해 글을 쓰고 싶었습니다. 하나는 실제 코딩 과정에서 자주 사용된다는 점이고, 다른 하나는 가끔 친구가 사용할 때 몇 가지 문제에 직면할 수 있다는 점입니다.
Promise는 실제로 JS 작성 방식에 가장 큰 영향을 미친 ES6의 API 기능 중 하나입니다.본 글은 실제 사용과정을 요약한 글입니다
파일 생성시간 2017-10-09를 보시면 미루는 버릇이 정말 심합니다. . . 아직은 실행력을 강화해야 합니다! 초심 잊지 말고 어서!
머리말 && 기본 개념
Promise는 JS 비동기성에 대한 솔루션입니다. 기존 콜백 함수와 비교할 때 Promise는 여러 콜백의 심각한 중첩 문제를 해결할 수 있습니다.
Promise 개체는 비동기 작업을 나타내며 보류, 이행 또는 거부의 세 가지 상태를 갖습니다. 상태 전환은 보류 중 -> 이행 또는 보류 중 -> 거부일 수 있으며, 이 프로세스는 일단 발생하면 되돌릴 수 없습니다.
개인적으로 Promise를 설명하는 부분은 실제로 두 부분으로 나누어야 한다고 생각합니다
Promise 생성자 사용 지침입니다.
Promise 프로토타입 객체의 일부 메서드.
Promise constructor
ES6에서는 Promise 객체가 Promise 인스턴스를 생성하는 데 사용되는 생성자라고 규정합니다.
Promise 생성자는 함수를 매개변수로 받아들이고, 함수의 두 매개변수는 확인(Resolve)과 거부(Reject)입니다. 이는 JavaScript 엔진에서 제공하는 두 가지 기능이므로 직접 배포할 필요가 없습니다.
resolve 함수의 기능은 Promise 객체의 상태를 "미완성"에서 "성공"으로 변경하는 것입니다(즉, 보류에서 이행으로). 비동기 작업이 성공하면 호출되고 비동기 작업의 결과가 나타납니다. 작업이 매개변수로 전달됩니다.
reject 함수의 기능은 Promise 개체의 상태를 "미완성"에서 "실패"(즉, 보류 중에서 거부됨)로 변경하는 것입니다. 비동기 작업에서 보고된 오류는 매개변수로 전달됩니다.
다음 코드는 Promise 인스턴스를 생성합니다.
function request() { return new Promise((resolve, reject) => { /* 异步操作成功 */ setTimeout(() => { resolve("success"); }, 1000); // 取消注释这里可以体现,Promise 的状态一旦变更就不会再变化的特性 // reject('error'); }); }
위의 new Promise()
를
request() .then(result => { console.info(result); }) .catch(error => { console.info(error); });
받은 후 catch를 사용하여 오류를 캡처하는 것 외에도 then
메서드를 사용하여 를 지정할 수도 있습니다. 해결
및 거부
콜백 함수 new Promise()
之后,除去用 catch 去捕获错误之外,也可以用 then
方法指定 resolve
和 reject
的回调函数
也能达到捕获错误的目的。
request().then( result => { console.info(result); }, error => { console.info(error); } );
原型上的方法
Promise.prototype.then()
p.then(onFulfilled, onRejected)
then 方法 是定义在 Promise.prototype 上的方法,如上面的例子一样,有两个参数,fulfilled 的回调函数和 rejected 的回调函数,第二个参数时可选的。
两个关键点:
then 方法的返回值是一个新的
Promise
实例,所以对于调用者而言,拿到一个Promise
对象,调用then
后仍然返回一个Promise
를 사용하면 오류 잡기 목적을 달성할 수도 있습니다.a(a1 => { b(a1, b1 => { c(b1, c1 => { d(c1, d1 => { console.log(d1); }); }); }); });
로그인 후 복사Prototype 메소드
- Promise.prototype.then()
a() .then(b) .then(c) .then(d) .then(d1 => { console.log(d1); }); //===== 可能上面的例子并不太好看 ===下面这样更直观 a() .then(a1 => b(a1)) .then(b1 => c(b1)) .then(c1 => d(c1)) .then(d1 => { console.log(d1); });
로그인 후 복사then 메소드는 Promise.prototype에 정의된 메소드로, 이행된 콜백 함수와 거부된 콜백 함수라는 두 개의 매개변수가 있습니다. 선택 과목.
두 가지 핵심 사항: - then 메소드의 반환 값은 새로운
then의 콜백 함수가 값을 반환하면 그때 반환된 Promise는 수락 상태가 되며, 반환된 값은 해당 상태를 수락하는 콜백 함수의 매개변수 값으로 사용됩니다. .
then의 콜백 함수에서 오류가 발생하면 그때 반환된 Promise는 거부 상태가 되며, 발생한 오류는 거부 상태의 콜백 함수의 매개변수 값으로 사용됩니다.
Promise
인스턴스이므로 호출자에게는 Promise
객체를 가져오고, < code>then, Promise
는 여전히 반환되며 해당 동작은 then의 콜백 함수 반환 값과 관련됩니다. 다음과 같습니다. - 다음의 콜백 함수가 이미 수락 상태인 Promise를 반환하면 그때 반환된 Promise도 수락 상태가 되며 해당 Promise의 수락 상태에 대한 콜백 함수의 매개변수 값은 반환된 Promise로 사용됩니다. 상태 콜백 함수의 매개변수 값을 수락합니다.
- 콜백 함수가 이미 거부된 상태인 Promise를 반환하는 경우 그때 반환된 Promise도 거부된 상태가 되며 해당 Promise의 거부된 상태에 대한 콜백 함수의 매개변수 값은 반환된 Promise 거부 상태 콜백 함수의 매개변수 값으로 사용됩니다.
콜백 함수가 보류 상태의 Promise를 반환하는 경우 그때 반환된 Promise의 상태도 보류 중이며 최종 상태는 동시에 해당 Promise의 최종 상태와 동일합니다. , 최종 상태가 됩니다. Promise가 최종 상태가 될 때 호출되는 콜백 함수의 매개변수는 동일합니다.
연쇄 통화. 중첩된 콜백의 코드 형식을 연결된 호출의 수직 모드로 변환합니다.
🎜🎜🎜예를 들어 콜백 형식: 콜백 지옥의 예🎜// 1. request().then( result => { console.info(result); }, error => { console.info(error); } ); // 2. request() .then(result => { console.info(result); }) .catch(error => { console.info(error); });
new Promise((resolve, reject) => { setTimeout(() => { resolve("reject"); }, 1000); }) .then( result => { console.log(result + "1"); throw Error(result + "1"); // 抛出一个错误 }, error => { console.log(error + ":1"); // 不会走到这里 } ) .then( result => { console.log(result + "2"); return Promise.resolve(result + "2"); }, error => { console.log(error + ":2"); } ); // reject1, Error: reject1:2
其实 它的行为与调用 Promise.prototype.then(undefined, onRejected) 相同。 (事实上, calling obj.catch(onRejected) 内部 calls obj.then(undefined, onRejected)).
// 1. request().then( result => { console.info(result); }, error => { console.info(error); } ); // 2. request() .then(result => { console.info(result); }) .catch(error => { console.info(error); });
如上这个例子:两种方式在使用,与结果基本上是等价的,但是 仍然推荐第二种写法,下面我会给出原因:
在 Promise 链中 Promise.prototype.then(undefined, onRejected),onRejected 方法无法捕获当前 Promise 抛出的错误,而后续的 .catch 可以捕获之前的错误。
代码冗余
new Promise((resolve, reject) => { setTimeout(() => { resolve("reject"); }, 1000); }) .then( result => { console.log(result + "1"); throw Error(result + "1"); // 抛出一个错误 }, error => { console.log(error + ":1"); // 不会走到这里 } ) .then( result => { console.log(result + "2"); return Promise.resolve(result + "2"); }, error => { console.log(error + ":2"); } ); // reject1, Error: reject1:2
如果使用 .catch 方法,代码会简化很多,这样实际上是延长了 Promise 链
new Promise((resolve, reject) => { setTimeout(() => { resolve("reject"); }, 1000); }) .then(result => { console.log(result + "1"); throw Error(result + "1"); // 抛出一个错误 }) .then(result => { console.log(result + "2"); return Promise.resolve(result + "2"); }) .catch(err => { console.log(err); }); // reject1, Error: reject1:2
Promise.prototype.finally()
暂未完全成为标准的一部分,处于:Stage 4
finally() 方法返回一个 Promise,在执行 then() 和 catch() 后,都会执行finally指定的回调函数。(回调函数中无参数,仅仅代表 Promise 的已经结束
等同于使用 .then + .catch 延长了原有的 Promise 链的效果,避免同样的语句需要在 then() 和 catch() 中各写一次的情况。
mdn-Promise-finally
Promise 对象上的方法
Promise.all() 用来处理 Promise 的并发
Promise.all 会将多个 Promise 实例封装成一个新的 Promise 实例,新的 promise 的状态取决于多个 Promise 实例的状态,只有在全体 Promise 都为 fulfilled 的情况下,新的实例才会变成 fulfilled 状态。;如果参数中 Promise 有一个失败(rejected),此实例回调失败(rejecte),失败原因的是第一个失败 Promise 的结果。
举个例子:
Promise.all([ new Promise(resolve => { setTimeout(resolve, 1000, "p1"); }), new Promise(resolve => { setTimeout(resolve, 2000, "p2"); }), new Promise(resolve => { setTimeout(resolve, 3000, "p3"); }) ]) .then(result => { console.info("then", result); }) .catch(error => { console.info("catch", error); }); // [p1,p2,p3] Promise.all([ new Promise(resolve => { setTimeout(resolve, 1000, "p1"); }), new Promise(resolve => { setTimeout(resolve, 2000, "p2"); }), Promise.reject("p3 error") ]) .then(result => { console.info("then", result); }) .catch(error => { console.info("catch", error); }); // p3 error
获取 cnode 社区的 精华贴的前十条内容
fetch("https://cnodejs.org/api/v1/topics?tab=good&limit=10") .then(res => res.json()) .then(res => { const fetchList = res.data.map(item => { return fetch(`https://cnodejs.org/api/v1/topic/${item.id}`) .then(res => res.json()) .then(res => res.data); }); Promise.all(fetchList).then(list => { console.log(list); }); });
Promise.race() 竞态执行
Promise.race 也会将多个 Promise 实例封装成一个新的Promise实例,只不过新的 Promise 的状态取决于最先改变状态的 Promise 实例的状态。
在前端最典型的一个用法是为 fetch api 模拟请求超时。
Promise.race([ fetch("https://cnodejs.org/api/v1/topics?tab=good&limit=10").then(res => res.json() ), new Promise((resolve, reject) => { setTimeout(reject, 1, "error"); }) ]) .then(result => { console.info("then", result); }) .catch(error => { console.info("catch", error); // 进入这里 });
上述例子中只要请求 未在 1 毫秒内结束就会进入 .catch() 方法中,虽然不能将请求取消,但是超时模拟却成功了
Promise.resolve(value) && Promise.reject(reason)
这两个方法都能用来创建并返回一个新的 Promise , 区别是 Promise.resolve(value) 携带进新的 Promise 状态是 fulfilled。而 Promise.reject(reason) 带来的 rejected
有的时候可以用来简化一些创建 Promise 的操作如:
const sleep = (time = 0) => new Promise(resolve => setTimeout(resolve, time)); // 这里创建一个 睡眠,并且打印的链 Promise.resolve() .then(() => { console.log(1); }) .then(() => sleep(1000)) .then(() => { console.log(2); }) .then(() => sleep(2000)) .then(() => { console.log(3); });
有时也用来 手动改变 Promise 链中的返回状态 ,当然这样实际上和 直接返回一个值,或者是 使用 throw Error 来构造一个错误,并无区别。到底要怎么用 就看个人喜好了
new Promise((resolve, reject) => { setTimeout(() => { resolve("resolve"); // 1. }, 1000); }) .then(result => { return Promise.reject("reject1"); // 2. }) .then( result => { return Promise.resolve(result + "2"); }, err => { return Promise.resolve(err); // 3. } ) .then(res => { console.log(res); // 4. }) .catch(err => { console.log(err + "err"); }); // reject1
几个例子
下面来看几个例子:
关于执行顺序,具体可搜索,js 循环
new Promise((resolve, reject) => { console.log("step 1"); resolve(); console.log("step 2"); }).then(() => { console.log("step 3"); }); console.log("step 4"); // step 1, step 2, step 4 , step 3
在使用 Promise 构造函数构造 一个 Promise 时,回调函数中的内容就会立即执行,而 Promise.then 中的函数是异步执行的。
关于状态不可变更
let start; const p = new Promise((resolve, reject) => { setTimeout(() => { start = Date.now(); console.log("once"); resolve("success"); }, 1000); }); p.then(res => { console.log(res, Date.now() - start); }); p.then(res => { console.log(res, Date.now() - start); }); p.then(res => { console.log(res, Date.now() - start); });
Promise 构造函数只执行一次,内部状态一旦改变,有了一个值,后续不论调用多少次then()都只拿到那么一个结果。
关于好像状态可以变更
const p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve("success"); }, 1000); }); const p2 = p1.then((resolve, reject) => { throw new Error("error"); }); console.log("p1", p1); console.log("p2", p2); setTimeout(() => { console.log("p1", p1); console.log("p2", p2); }, 2000);
观察这一次的打印
第一次打印出两个 Promise 的时候都是 pending ,因为 p2 是基于 p1 的结果,p1 正在 pending ,立即打印出的时候肯定是 pending ;第二次打印的时候,因为 p1
的状态为 resolved ,p2 为 rejected ,这个并不是已经为 fulfilled 状态改变为 rejected ,而是 p2
是一个新的 Promise 实例,then() 返回新的 Promise 实例。
关于透传
Promise.resolve(11) .then(1) .then(2) .then(3) .then(res => { console.info("res", res); }); // 11
给 then 方法传递了一个非函数的值,等同于 then(null),会导致穿透的效果,就是直接过掉了这个 then() ,直到符合规范的 then() 为止。
Promise 的串行调用
使用 Array.reduce 方法串行执行 Promise
const sleep = (time = 0) => new Promise(resolve => setTimeout(resolve, time)); [1000, 2000, 3000, 4000].reduce((Promise, item, index) => { return Promise.then(res => { console.log(index + 1); return sleep(item); }); }, Promise.resolve()); // 在分别的等待时间后输出 1,2,3,4
这篇文章到这里就基本上结束了,相信 如果能理解上面的内容,并且在实际项目中使用的话。应该会让工作更高效吧,对于新的异步使用应该也会更加的得心应手。Promise 的使用相对简单,可能后续再出一篇如何实现一个 Promise 吧。
위 내용은 약속이란 무엇입니까? 약속 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











HTML의 테이블 테두리 안내. 여기에서는 HTML의 테이블 테두리 예제를 사용하여 테이블 테두리를 정의하는 여러 가지 방법을 논의합니다.

HTML 여백-왼쪽 안내. 여기에서는 HTML margin-left에 대한 간략한 개요와 코드 구현과 함께 예제를 논의합니다.

HTML의 Nested Table에 대한 안내입니다. 여기에서는 각 예와 함께 테이블 내에 테이블을 만드는 방법을 설명합니다.

HTML 테이블 레이아웃 안내. 여기에서는 HTML 테이블 레이아웃의 값에 대해 예제 및 출력 n 세부 사항과 함께 논의합니다.

HTML 입력 자리 표시자 안내. 여기서는 코드 및 출력과 함께 HTML 입력 자리 표시자의 예를 논의합니다.

HTML 순서 목록에 대한 안내입니다. 여기서는 HTML Ordered 목록 및 유형에 대한 소개와 각각의 예에 대해서도 설명합니다.

HTML에서 텍스트 이동 안내. 여기서는 Marquee 태그가 구문과 함께 작동하는 방식과 구현할 예제에 대해 소개합니다.

HTML onclick 버튼에 대한 안내입니다. 여기에서는 각각의 소개, 작업, 예제 및 다양한 이벤트의 onclick 이벤트에 대해 설명합니다.
