이것은 실제 문제가 아닙니다. 저는 약속이 어떻게 생성되는지 이해하려고 노력하고 있습니다.
setTimeout처럼 아무것도 반환하지 않는 함수에 대한 약속을 만드는 방법을 이해해야합니다.
내가 가지고 있다고 가정합니다.
function async(callback){
setTimeout(function(){
callback();
}, 5000);
}
async(function(){
console.log('async called back');
});
준비가 완료된 async
후 반환 할 수 있는 프라 미스를 어떻게 생성 합니까?setTimeout
callback()
포장하면 어딘가에 걸릴 것이라고 생각했습니다.
function setTimeoutReturnPromise(){
function promise(){}
promise.prototype.then = function() {
console.log('timed out');
};
setTimeout(function(){
return ???
},2000);
return promise;
}
하지만이 이상은 생각할 수 없습니다.
답변
업데이트 (2017)
2017 년에는 Promise가 JavaScript에 내장되어 ES2015 사양에 의해 추가되었습니다 (폴리 필은 IE8-IE11과 같은 오래된 환경에서 사용 가능). 그들이 사용했던 구문은 당신이 Promise
생성자 ( Promise
executor )에 전달하는 콜백을 사용합니다.이 콜백 은 인자로 프라 미스를 해결 / 거부하는 함수를받습니다.
첫째, async
이제 JavaScript에서 의미가 있기 때문에 (특정 컨텍스트에서는 키워드 일뿐 임에도 불구하고) later
혼란을 피하기 위해 함수의 이름으로 사용하겠습니다 .
기본 지연
네이티브 프라 미스 (또는 충실한 폴리 필)를 사용하면 다음과 같습니다.
function later(delay) {
return new Promise(function(resolve) {
setTimeout(resolve, delay);
});
}
그 버전 가정합니다 setTimeout
그 준수의 브라우저에 대한 정의 곳 setTimeout
이 비 브라우저 환경에서 진실하지 않을 수 있습니다 (간격 후에을 제공하지 않는 콜백에 인수를 전달하지 않으며,로 사용하지 않았다 Firefox에서는 사실이지만 지금은 그렇습니다. Chrome에서는 사실이며 IE8에서도 마찬가지입니다.)
가치가있는 기본 지연
함수가 선택적으로 해상도 값을 전달하도록 setTimeout
하려면 지연 후 추가 인수를 제공 한 다음 호출시 콜백에 전달할 수있는 모호한 최신 브라우저에서이를 수행 할 수 있습니다 (현재 Firefox 및 Chrome, IE11 + , 아마도 Edge; IE8 또는 IE9가 아니라 IE10에 대한 정보 없음) :
function later(delay, value) {
return new Promise(function(resolve) {
setTimeout(resolve, delay, value); // Note the order, `delay` before `value`
/* Or for outdated browsers that don't support doing that:
setTimeout(function() {
resolve(value);
}, delay);
Or alternately:
setTimeout(resolve.bind(null, value), delay);
*/
});
}
ES2015 + 화살표 기능을 사용하는 경우 더 간결 할 수 있습니다.
function later(delay, value) {
return new Promise(resolve => setTimeout(resolve, delay, value));
}
또는
const later = (delay, value) =>
new Promise(resolve => setTimeout(resolve, delay, value));
값이있는 취소 가능한 지연
시간 제한을 취소 할 수 있도록하려면 약속을 later
취소 할 수 없기 때문에 에서 약속을 반환 할 수 없습니다.
그러나 우리는 프라 미스에 대한 cancel
메소드와 접근자를 가진 객체를 쉽게 반환 할 수 있으며 취소시 프라 미스를 거부 할 수 있습니다.
const later = (delay, value) => {
let timer = 0;
let reject = null;
const promise = new Promise((resolve, _reject) => {
reject = _reject;
timer = setTimeout(resolve, delay, value);
});
return {
get promise() { return promise; },
cancel() {
if (timer) {
clearTimeout(timer);
timer = 0;
reject();
reject = null;
}
}
};
};
라이브 예 :
const later = (delay, value) => {
let timer = 0;
let reject = null;
const promise = new Promise((resolve, _reject) => {
reject = _reject;
timer = setTimeout(resolve, delay, value);
});
return {
get promise() { return promise; },
cancel() {
if (timer) {
clearTimeout(timer);
timer = 0;
reject();
reject = null;
}
}
};
};
const l1 = later(100, "l1");
l1.promise
.then(msg => { console.log(msg); })
.catch(() => { console.log("l1 cancelled"); });
const l2 = later(200, "l2");
l2.promise
.then(msg => { console.log(msg); })
.catch(() => { console.log("l2 cancelled"); });
setTimeout(() => {
l2.cancel();
}, 150);
2014 년의 원래 답변
일반적으로 약속 라이브러리가 있습니다 (하나는 직접 작성하거나 여러 개 중 하나). 해당 라이브러리에는 일반적으로 생성하고 나중에 “해결”할 수있는 객체가 있으며, 해당 객체에는 얻을 수있는 “약속”이 있습니다.
그러면 다음 later
과 같은 경향이 있습니다.
function later() {
var p = new PromiseThingy();
setTimeout(function() {
p.resolve();
}, 2000);
return p.promise(); // Note we're not returning `p` directly
}
질문에 대한 의견에서 다음과 같이 질문했습니다.
자신 만의 약속 라이브러리를 만들려고합니까?
그리고 당신은 말했다
나는 아니었지만 이제는 그것이 실제로 내가 이해하려고 노력한 것 같습니다. 도서관이하는 방법
이러한 이해를 돕기 위해 원격으로 Promises-A를 준수하지 않는 매우 기본적인 예가 있습니다. Live Copy
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Very basic promises</title>
</head>
<body>
<script>
(function() {
// ==== Very basic promise implementation, not remotely Promises-A compliant, just a very basic example
var PromiseThingy = (function() {
// Internal - trigger a callback
function triggerCallback(callback, promise) {
try {
callback(promise.resolvedValue);
}
catch (e) {
}
}
// The internal promise constructor, we don't share this
function Promise() {
this.callbacks = [];
}
// Register a 'then' callback
Promise.prototype.then = function(callback) {
var thispromise = this;
if (!this.resolved) {
// Not resolved yet, remember the callback
this.callbacks.push(callback);
}
else {
// Resolved; trigger callback right away, but always async
setTimeout(function() {
triggerCallback(callback, thispromise);
}, 0);
}
return this;
};
// Our public constructor for PromiseThingys
function PromiseThingy() {
this.p = new Promise();
}
// Resolve our underlying promise
PromiseThingy.prototype.resolve = function(value) {
var n;
if (!this.p.resolved) {
this.p.resolved = true;
this.p.resolvedValue = value;
for (n = 0; n < this.p.callbacks.length; ++n) {
triggerCallback(this.p.callbacks[n], this.p);
}
}
};
// Get our underlying promise
PromiseThingy.prototype.promise = function() {
return this.p;
};
// Export public
return PromiseThingy;
})();
// ==== Using it
function later() {
var p = new PromiseThingy();
setTimeout(function() {
p.resolve();
}, 2000);
return p.promise(); // Note we're not returning `p` directly
}
display("Start " + Date.now());
later().then(function() {
display("Done1 " + Date.now());
}).then(function() {
display("Done2 " + Date.now());
});
function display(msg) {
var p = document.createElement('p');
p.innerHTML = String(msg);
document.body.appendChild(p);
}
})();
</script>
</body>
</html>
답변
이것은 원래 질문에 대한 답이 아닙니다. 그러나 원래의 질문은 실제 문제가 아니므로 문제가되지 않아야합니다. 나는 친구에게 자바 스크립트의 프라 미스와 프라 미스와 콜백의 차이점을 설명하려고 노력했다.
아래 코드는 설명으로 사용됩니다.
//very basic callback example using setTimeout
//function a is asynchronous function
//function b used as a callback
function a (callback){
setTimeout (function(){
console.log ('using callback:');
let mockResponseData = '{"data": "something for callback"}';
if (callback){
callback (mockResponseData);
}
}, 2000);
}
function b (dataJson) {
let dataObject = JSON.parse (dataJson);
console.log (dataObject.data);
}
a (b);
//rewriting above code using Promise
//function c is asynchronous function
function c () {
return new Promise(function (resolve, reject) {
setTimeout (function(){
console.log ('using promise:');
let mockResponseData = '{"data": "something for promise"}';
resolve(mockResponseData);
}, 2000);
});
}
c().then (b);