Promise, async 및 await
readFile("example.txt", function(err, contents) {
if (err) {
throw err;
}
writeFile("example.txt", function(err) {
if (err) {
throw err;
}
console.log("File was written!");
});
});
method1(function(err, result) {
if (err) {
throw err;
}
method2(function(err, result) {
if (err) {
throw err;
}
method3(function(err, result) {
if (err) {
throw err;
}
method4(function(err, result) {
if (err) {
throw err;
}
method5(result);
});
});
});
});
지옥에 여러 가지 방법을 끼워 넣으면 복잡한 코드를 만들 수 있고 이해하기 어렵고 디버깅하기 어렵다.더 복잡한 기능을 실현하려고 할 때, 리셋 함수에도 문제가 존재할 수 있다.
Promise 정의
Promise는 비동기 프로그래밍의 해결 방안으로 전통적인 해결 방안인 리셋 함수와 사건보다 더욱 합리적이고 강력하다.이것은 지역 사회가 최초로 제기하고 실현한 것으로 ES6는 이를 언어 표준에 쓰고 용법을 통일시켰으며 원생은 Promise 대상을 제공했다.
이른바 Promise란 간단하게 말하면 하나의 용기로 미래에 끝날 사건(일반적으로 비동기적인 조작)의 결과를 저장하고 있다.문법적으로 프로미스는 비동기적인 조작에 대한 정보를 얻을 수 있는 대상이다.Promise는 다양한 비동기식 작업을 동일한 방법으로 처리할 수 있는 통일된 API를 제공합니다.
Promise 특징
Promise 대상이 있으면 비동기 조작을 동기화 조작의 절차로 표현할 수 있고 층층이 끼워 넣은 리셋 함수를 피할 수 있다.그 밖에 Promise 대상은 통일된 인터페이스를 제공하여 비동기적인 조작을 제어하는 것을 더욱 쉽게 한다.
기본용법
Promise 객체는 Promise 인스턴스를 생성하는 데 사용되는 구조 함수입니다.
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* */){
resolve(value);
} else {
reject(error);
}
});
Promise 구조 함수는 하나의 함수를 매개 변수로 받아들인다. 이 함수의 두 매개 변수는 각각resolve와reject이다.그것들은 두 개의 함수로 자바스크립트 엔진에서 제공하며 스스로 배치할 필요가 없다.
Promise 실례가 생성된 후, then 방법으로 각각resolved 상태와rejected 상태의 리셋 함수를 지정할 수 있습니다.
promise.then(function(value) {
// success
}, function(error) {
// failure
});
then 방법은 두 개의 리셋 함수를 매개 변수로 받아들일 수 있다.첫 번째 리셋 함수는 Promise 대상의 상태가resolved로 변할 때 호출되고, 두 번째 리셋 함수는 Promise 대상의 상태가rejected로 변할 때 호출됩니다.그 중에서 두 번째 함수는 선택할 수 있으며 반드시 제공해야 하는 것은 아니다.이 두 함수는 Promise 객체에서 전달되는 값을 매개 변수로 사용합니다.
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve('done'), ms);
});
}
timeout(100).then((value) => {
console.log(value);
});
resolve 함수와reject 함수를 호출할 때 파라미터가 있으면 파라미터가 리셋 함수에 전달됩니다.reject 함수의 매개 변수는 일반적으로 Error 대상의 실례로 던지는 오류를 나타낸다.resolve 함수의 매개 변수는 정상적인 값 이외에 다른 Promise 실례일 수도 있습니다.
const p1 = new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('fail')), 3000)
})
const p2 = new Promise(function (resolve, reject) {
setTimeout(() => resolve(p1), 1000)
})
p2.then(result => console.log(result)).catch(error => console.log(error))
// Error: fail
p1은 Promise로 3초 후에 rejected로 바뀝니다.p2의 상태는 1초 후에 바뀌고,resolve 방법은 p1을 되돌려줍니다.p2가 다른 Promise로 되돌아왔기 때문에 p2 자신의 상태가 무효입니다. p1의 상태가 p2의 상태를 결정합니다.그래서 뒤의 then 문장은 모두 후자 p1을 대상으로 한다.또 2초가 지나자 p1은rejected로 바뀌어catch 방법이 지정한 리셋 함수를 촉발합니다.
Resolve나reject를 호출하면 Promise의 매개 변수 함수의 실행이 끝나지 않습니다.
new Promise((resolve, reject) => {
resolve(1);
console.log(2);
}).then(r => {
console.log(r);
});
// 2
// 1
resolve (1) 를 호출한 후 뒤에 있는 console.log (2) 는 실행되고 먼저 출력됩니다.즉시resolved의Promise는 이번 이벤트 순환의 끝에서 실행되며, 항상 이번 순환의 동기화 작업보다 늦기 때문입니다.
일반적으로 Resolve나reject를 호출하면 Promise의 사명이 완성됩니다. 후속 작업은 then 방법에 넣어야 하며, 직접resolve나reject의 뒤에 쓰지 말아야 합니다.그래서 그것들 앞에 리턴 문장을 덧붙이는 것이 좋다. 이렇게 하면 의외의 일이 없을 것이다.
new Promise((resolve, reject) => {
return resolve(1);
//
console.log(2);
})
finally()
finally 메서드는 Promise 객체의 마지막 상태에 관계없이 수행할 작업을 지정하는 데 사용됩니다.이 방법은 ES2018에서 표준을 도입한 것이다.
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
promise의 마지막 상태를 막론하고,then이나catch가 지정한 리셋 함수를 실행한 후,finally 방법으로 지정한 리셋 함수를 실행합니다.
결정된 Promise
const p = Promise.resolve('foo')
//
const p = new Promise(resolve => resolve('foo'))
const p = Promise.reject(' ');
//
const p = new Promise((resolve, reject) => reject(' '))
상태가 결정된 Promise 인스턴스를 반환합니다.
실행자 오류
실행기 내부에서 오류가 발생하면 Promise의 처리 거부 함수가 호출됩니다.
let promise = new Promise(function(resolve, reject) {
throw new Error("Explosion!");
});
promise.catch(function(error) {
console.log(error.message); // "Explosion!"
});
직렬 연결
let p1 = new Promise(function(resolve, reject) {
resolve(42);
});
p1.then(function(value) {
console.log(value);
}).then(function() {
console.log("Finished");
});
직렬 버전 코드 중 p1.then () 의 호출은 두 번째 Promise를 되돌려주고 이 상향 조정에 then () 을 사용합니다.첫 번째 Promise가 결의된 후에만 두 번째 then () 의 완성 처리 함수가 호출됩니다.
여러 Promise 응답
개별 교체 가능 객체 (예: 배열) 를 매개변수로 수신하고 Promise 를 반환합니다.이 교체 가능한 대상의 요소는 모두 Promise입니다. 이 요소가 모두 완성된 후에만 되돌아오는 Promise가 완성됩니다.
let p1 = new Promise(function(resolve, reject) {
resolve(42);
});
let p2 = new Promise(function(resolve, reject) {
resolve(43);
});
let p3 = new Promise(function(resolve, reject) {
resolve(44);
});
let p4 = Promise.all([p1, p2, p3]);
p4.then(function(value) {
console.log(Array.isArray(value)); // true
console.log(value[0]); // 42
console.log(value[1]); // 43
console.log(value[2]); // 44
});
감시가 필요한 Promise를 포함하는 교체 가능한 대상을 받아들여 새로운 Promise로 되돌려줍니다. 그러나 원본 Promise 중 하나가 해결되면 되돌아오는 Promise는 즉시 해결됩니다.그리고 모든 Promise가 완성되기를 기다리는 Promise.all () 방법이 다르기 때문에 원본 Promise에서 임의로 완성될 때 Promise.race() 메서드가 반환하는 Promise는 응답할 수 있습니다.
let p1 = Promise.resolve(42);
let p2 = new Promise(function(resolve, reject) {
resolve(43);
});
let p3 = new Promise(function(resolve, reject) {
resolve(44);
});
let p4 = Promise.race([p1, p2, p3]);
p4.then(function(value) {
console.log(value); // 42
});
Promise 단점
async
async function f() {
return 'hello world';
}
f().then(v => console.log(v))
// "hello world"
위 코드에서 함수 f 내부return 명령이 되돌아오는 값은 then 방법 리셋 함수에 의해 수신됩니다.
async function f() {
throw new Error(' ');
}
f().catch(
e => console.log(e)
)
// Error:
async function asyncTest() {
let getUrl = await fetch();
console.log(getUrl);
let downloadUrl = await download();
console.log(downloadUrl);
return 'complete';
}
asyncTest().then(console.log)
function fetch() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('fetchDone');
}, 1000);
});
}
function download() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('downloadDone');
}, 2000);
});
}
위 코드에서 캡처 하나와 다운로드 하나를 시뮬레이션했습니다. 이 두 작업이 모두 끝나야만 then 방법의 console를 실행할 수 있습니다.log.
await
async function f() {
return await 123;
}
f().then(v => console.log(v))
// 123
await 명령의 매개 변수는 수치 123입니다. 이것은 Promise 대상으로 바뀌고 즉시resolve입니다.
async function f() {
await Promise.reject(' ');
}
f().then(v => console.log(v)).catch(e => console.log(e))
//
위 코드에서await 문장 앞에return이 없지만,reject 방법의 매개 변수는catch 방법의 리셋 함수에 전송됩니다.여기에await 앞에return을 넣으면 효과는 같다.
async function f() {
await Promise.reject(' ');
await Promise.resolve('hello world'); //
}
async function f() {
try {
await Promise.reject(' ');
} catch(e) {
}
return await Promise.resolve('hello world');
}
f().then(v => console.log(v))
// hello world
또 다른 방법은await 뒤에 있는Promise 대상과catch 방법을 따라 앞에 발생할 수 있는 오류를 처리하는 것입니다.
async function f() {
await Promise.reject(' ')
.catch(e => console.log(e));
return await Promise.resolve('hello world');
}
f().then(v => console.log(v))
//
// hello world
주의점
async function myFunction() {
try {
await somethingThatReturnsAPromise();
} catch (err) {
console.log(err);
}
}
//
async function myFunction() {
await somethingThatReturnsAPromise()
.catch(function (err) {
console.log(err);
});
}
//
async function test() {
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
}
function getFoo() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('getFoo');
resolve()
}, 2000);
})
}
function getBar() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
console.log('getBar');
resolve()
}, 2000);
})
}
test()
//
async function test() {
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
}
async function test() {
let promises = [function1, function2, function3]
promises.forEach(function (fun) {
const t = await fun();
console.log(t)
});
}
function function1() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('function1')
}, 2000)
})
}
function function2() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('function2')
}, 2000)
})
}
function function3() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('function3')
}, 2000)
})
}
test()
promises.forEach(async function (fun) {
const t = await fun();
console.log(t)
});
상기 코드가 정상적으로 작동하지 않을 수 있습니다. 왜냐하면 이 때 세 가지 비동기적인 조작은 병행 실행, 즉 동시 실행이 될 것이지 계발 실행이 아니기 때문입니다.정확한 작법은 for순환을 채택하는 것이다.
for (let i of promises) {
const t = await i()
console.log(t)
}
async function dbFuc(db) {
async function test() {
let promises = [function1(), function2(), function3()]
let results = await Promise.all(promises);
console.log(results)
}
참조 링크
ECMAScript 6 시작
ES6 이해
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.