이전 글에서는 주로 동기화와 비동기성, '실행 스택', '메시지 큐', 그리고 각각에서 파생되는 '매크로 태스크'와 '마이크로 태스크'에 대해 이야기했습니다. 이해하세요. 다음 링크로 이동할 수 있습니다:
https://www.jianshu.com/p/61e7844e68d8
Ajax 요청, 타이머 등을 포함하여 매크로 작업과 마이크로 작업은 모두 비동기식입니다. Promise에 대해 미리 살펴보겠습니다. , 비동기 문제를 해결하는 방법이라는 것을 알면서 우리가 일반적으로 사용하는 방법은 무엇입니까?
많은 지식 포인트가 포함되어 있기 때문에 이 기사에서는 주로 콜백 함수와 약속에 대해 설명합니다.
一, 콜백 함수
先上代码: function f2() { console.log('2222') } function f1(callback){ console.log('111') setTimeout(function () { callback(); }, 5000); console.log('3333') } f1(f2); 先看下打印值是: 111 3333 五秒后2222
는 메인 스레드가 실행을 종료하는 것과 동일하며 콜백 함수를 통해 f2 함수가 호출됩니다. 이는 아무런 문제가 없습니다. 그런데 아래 예를 보세요.
现在我们读取一个文件,fileReader就是一个异步请求 // 这个异步请求就是通过回调函数的方式获取的 var reader = new FileReader() var file = input.files[0] reader.readAsText(file, 'utf-8',function(err, data){ if(err){ console.log(err) } else { console.log(data) } })
지금은 매우 좋아 보이지만 파일 업로드에 오류가 있으면 콜백에서 판단해야 합니다. 이 파일 읽기를 마친 다음 여러 파일을 읽으면 어떻게 될까요? 이렇게 작성해야 할까요?
读取完文件1之后再接着读取文件2、3 var reader = new FileReader() var file = input.files[0] reader.readAsText(file1, 'utf-8',function(err1, data1){ if(err1){ console.log(err1) } else { console.log(data1) } reader.readAsText(file2, 'utf-8',function(err2, data2){ if(err2){ console.log(err2) } else { console.log(data2) } reader.readAsText(file3, 'utf-8',function(err3, data3){ if(err3){ console.log(err3) } else { console.log(data3) } }) }) })
이렇게 작성하면 요구 사항을 충족할 수 있지만 이 코드의 가독성이 상대적으로 떨어지고 우아해 보이지도 않는데, 이를 흔히 '콜백 지옥'이라고 부릅니다. 그렇다면 이 중첩된 콜백을 해독하는 방법은 무엇입니까? ES6는 우리에게 약속을 제공합니다:
2. 약속
먼저, 약속이 문자 그대로 무엇인지 이해합시다. 약속은 약속과 보증으로 해석될 수 있습니다.
내 여자친구가 나에게 뭔가를 해달라고 요청했습니다. 아직 완료하지 않았지만 이 문제가 성공할 것이라고 약속합니다. ) 또는 실패(거부)되어 대기 상태(보류)가 있습니다.
还是先上例子 let promise = new Promise((resolve, reject) => { setTimeout(() => { resolve(2000) // 成功以后这个resolve会把成功的结果捕捉到 // reject(2000) // 失败以后这个reject会把失败的结果捕捉到 }, 1000) console.log(1111) }) promise.then(res => { console.log(res) // then里面第一个参数就能拿到捕捉到的成功结果 }, err =>{ console.log(res)// then里面第二个参数就能拿到捕捉到的失败结果 }) 打印结果: 1111 2000(一秒以后)
1. Then 체인 연산
Promise 객체의 then 메소드는 새로운 Promise 객체를 반환하므로 체인을 통해 then 메소드를 호출할 수 있습니다.
Then 메서드는 두 가지 함수를 매개변수로 받습니다. 첫 번째 매개변수는 Promise가 성공적으로 실행될 때의 콜백입니다. 위의 예에서 캡처하는 두 번째 매개변수는 실패한 콜백입니다. .
두 함수 중 하나만 호출됩니다. 이 문장을 어떻게 이해하시나요?
여자친구가 토마토 계란 수프를 만들어 달라고 합니다. 당신이 하든 안 하든 테이크아웃을 하세요.
함수의 반환 값은 그때 반환되는 Promise 객체를 생성하는 데 사용됩니다. 이 문장은 어떻게 이해해야 할까요? 위의 예는 다음과 같습니다.
let promise = new Promise((resolve, reject) => { setTimeout(() => { resolve(2000) }, 1000) console.log(1111) }) promise.then(res => { console.log(res) // 这个地方会打印捕捉到的2000 return res + 1000 // 这个函数的返回值,返回的就是这个promise对象捕捉到的成功的值 }).then(res => { console.log(res) //这个地方打印的就是上一个promise对象return的值 }) 所以打印顺序应该是: 1111 2000 3000
방금 then이 두 개의 매개변수를 허용하는 것을 보았습니다. 하나는 성공 콜백이고 다른 하나는 실패 콜백입니다. then 외에도 promise는 catch 메소드를 제공합니다. :
2, catch 캡처 작업
이 catch는 오류 콜백을 캡처하도록 특별히 설계되었습니다. 먼저 예제를 살펴보겠습니다.
let promise = new Promise((resolve, reject) => { setTimeout(() => { reject(2000) // 失败以后这个reject会把失败的结果捕捉到 }, 1000) console.log(1111) }) promise.catch(res => { console.log(res) // catch里面就能拿到捕捉到的失败结果 }) 打印结果: 1111 2000(一秒以后)
then과 catch 외에도 promise에는 all과 race라는 두 가지 구문이 있습니다. 간략하게:
3. all
이제 이러한 요구 사항이 있습니다. 세 가지 인터페이스 A, B, C가 있습니다. 네 번째 요청은 세 가지 인터페이스가 모두 성공한 후에만 시작될 수 있습니다.
연속 호출
let getInfoA = new Promise((resolve, reject) => { console.log('小A开始执行了') resolve() }).then(res => { let getInfoB = new Promise((resolve, reject) => { console.log('小B开始执行了') resolve() }).then(res => { let getInfoC = new Promise((resolve, reject) => { console.log('小C开始执行了') resolve() }).then(res => { console.log('全都执行完了!') }) }) })
계층이 하나씩 이어져 있어서 그다지 우아해 보이지는 않습니다
all
let getInfoA = new Promise((resolve, reject) => { console.log('小A开始执行了') resolve() }) let getInfoB = new Promise((resolve, reject) => { console.log('小B开始执行了') resolve() }) let getInfoC = new Promise((resolve, reject) => { console.log('小C开始执行了') resolve() }) Promise.all([getInfoA, getInfoB, getInfoC]).then(res => { console.log('全都执行完了!') })
Promise 객체의 배열을 매개변수로 받습니다. 이 배열에 있는 모든 Promise 객체의 상태가 해결되거나 거부될 때. , then 메소드를 호출합니다. 너무 완벽하고, 너무 우아해요.
4. Race
이제 인터페이스 A, B, C인 또 다른 요구 사항이 있습니다. 둘 중 하나가 응답하는 한 인터페이스 D를 조정할 수 있습니다. 그러면 어떻게 구현할까요?
1. 전통적인 방식
let getInfoA = new Promise((resolve, reject) => { console.log('小A开始执行了') setTimeout((err => { resolve('小A最快') }),1000) }).then(res =>{ console.log(res) }) let getInfoB = new Promise((resolve, reject) => { console.log('小B开始执行了') setTimeout((err => { resolve('小B最快') }),1001) }).then(res =>{ console.log(res) }) let getInfoC = new Promise((resolve, reject) => { console.log('小C开始执行了') setTimeout((err => { resolve('小C最快') }),1002) }).then(res =>{ console.log(res) }) 打印结果 小A开始执行了 小B开始执行了 小C开始执行了 小A最快
이 방식은 세번을 작성해야 하는데 그리 우아해 보이지는 않네요.
2. race
let getInfoA = new Promise((resolve, reject) => { console.log('小A开始执行了') setTimeout((err => { resolve('小A最快') }),1000) }) let getInfoB = new Promise((resolve, reject) => { console.log('小B开始执行了') setTimeout((err => { resolve('小B最快') }),1001) }) let getInfoC = new Promise((resolve, reject) => { console.log('小C开始执行了') setTimeout((err => { resolve('小C最快') }),1002) }) Promise.race([getInfoA, getInfoB, getInfoC]).then(res => { console.log(res) }) 打印结果 小A开始执行了 小B开始执行了 小C开始执行了 小A最快
Promise.all과 유사하게 Promise.race는 Promise 객체의 배열을 매개변수로 사용합니다. 차이점은 배열의 Promsie 상태 중 하나가 해결되거나 거부되는 한 다음을 호출할 수 있다는 것입니다. .then 메소드.
Promise는 ES6에서 비동기 문제를 해결하기 위해 사용하는 방법입니다. 예를 들어 우리가 자주 사용하는 axios는 promise로 캡슐화되어 있어 사용하기 매우 편리합니다.
Promise 외에도 ES6는 async 및 Wait에 대한 궁극적인 트릭을 제공합니다. 이 두 가지 지식 블록은 상대적으로 크기 때문에 다음 기사에서 이에 대해 이야기하겠습니다.
개인 WeChat 공개 계정: Jerry는 할 말이 있으면 주로 기술 관련 기사와 독서 노트를 게시합니다.
추천 튜토리얼: "JS Tutorial"
위 내용은 약속 이해, 비동기, 대기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!