약속 체인에서 setTimeout 사용


115

여기에서 약속에 대해 머리를 감싸려고합니다. 여기에서 첫 번째 요청에 링크 세트를 가져오고 다음 요청에 첫 번째 링크의 내용을 가져옵니다.하지만 다음 약속 객체를 반환하기 전에 지연을 만들고 싶습니다. 그래서 사용합니다. 그것에 setTimeout. 그러나 그것은 나에게 다음과 같은 JSON 오류를 제공합니다 ( without setTimeout() it works just fine)

SyntaxError : JSON.parse : JSON 데이터의 1 행 1 열에 예기치 않은 문자가 있습니다.

왜 실패했는지 알고 싶습니다.

let globalObj={};
function getLinks(url){
    return new Promise(function(resolve,reject){

       let http = new XMLHttpRequest();
       http.onreadystatechange = function(){
            if(http.readyState == 4){
              if(http.status == 200){
                resolve(http.response);
              }else{
                reject(new Error());
              }
            }           
       }
       http.open("GET",url,true);
       http.send();
    });
}

getLinks('links.txt').then(function(links){
    let all_links = (JSON.parse(links));
    globalObj=all_links;

    return getLinks(globalObj["one"]+".txt");

}).then(function(topic){


    writeToBody(topic);
    setTimeout(function(){
         return getLinks(globalObj["two"]+".txt"); // without setTimeout it works fine 
         },1000);
});

1
return에만 부모 함수에 함수를 특정하고, 수익을, 그리고 당신이 비동기 방식에서 반환 할 수 있습니다.
adeneo

2
공지 사항이 있습니다 훨씬 더 나은 방법 를 사용하는 것보다이 코드를 구조화하는 globalObj.
Bergi

JSON.parse던지는 곳 ? setTimeout하나의 then콜백 이 있는지 여부가 이전 then콜백 의 호출에 영향을 미친다 는 사실을 믿기가 어렵습니다 .
Bergi

답변:


191

promise 체인을 계속 유지하려면 핸들러 setTimeout()에서 promise를 반환하지 않기 때문에했던 방식을 사용할 수 없습니다 .then(). setTimeout()콜백 에서 반환하므로 좋지 않습니다.

대신 다음과 같이 간단한 지연 함수를 만들 수 있습니다.

function delay(t, v) {
   return new Promise(function(resolve) { 
       setTimeout(resolve.bind(null, v), t)
   });
}

그리고 다음과 같이 사용하십시오.

getLinks('links.txt').then(function(links){
    let all_links = (JSON.parse(links));
    globalObj=all_links;

    return getLinks(globalObj["one"]+".txt");

}).then(function(topic){
    writeToBody(topic);
    // return a promise here that will be chained to prior promise
    return delay(1000).then(function() {
        return getLinks(globalObj["two"]+".txt");
    });
});

여기에서 .then()핸들러 에서 프라 미스를 반환 하므로 적절하게 연결됩니다.


Promise 개체에 지연 메서드를 추가 한 다음 다음 .delay(x)과 같이 약속에 대한 메서드 를 직접 사용할 수도 있습니다 .

function delay(t, v) {
   return new Promise(function(resolve) { 
       setTimeout(resolve.bind(null, v), t)
   });
}

Promise.prototype.delay = function(t) {
    return this.then(function(v) {
        return delay(t, v);
    });
}


Promise.resolve("hello").delay(500).then(function(v) {
    console.log(v);
});

또는 이미 메소드가 내장 된 Bluebird promise 라이브러리 를 사용하십시오 .delay().


1
resolve 함수는 then () .. 내부의 함수이므로 setTimeout (resolve, t)는 setTimeout (function () {return ....}, t)가 아닌지 ... 그래서 왜 작동할까요?
AL-zami

2
AL-zami @ - delay()애프터 해결 될 것입니다 약속을 반환합니다 setTimeout().
jfriend00 2016-09-16

약속을 쉽게 지연시키기 위해 setTimeout에 대한 약속 래퍼를 만들었습니다. github.com/zengfenfei/delay
Kevin

4
@pdem- v지연 약속을 해결하여 약속 체인을 전달하려는 선택적 값입니다. resolve.bind(null, v)대신에 function() {resolve(v);} 작동합니다 어느.
jfriend00

감사합니다 ... 프로토 타입 지연은 작동했지만 함수 >>> .then 문은 작동하지 않았습니다. t는 정의되지 않았습니다.
Christian Matthew

76
.then(() => new Promise((resolve) => setTimeout(resolve, 15000)))

최신 정보:

비동기 함수에서 잠이 필요할 때 던져 넣습니다.

await new Promise(resolve => setTimeout(resolve, 1000))

그렇게 비동기 함수 안에서 잠을 잘 수는 없나요? await new Promise (resolve => setTimeout (resolve, 1000));
Anthony Moon Beam Toorie

@AnthonyMoonBeamToorie 고정, ty
Igor Korsakov

52

더 짧은 ES6 버전의 답변 :

const delay = t => new Promise(resolve => setTimeout(resolve, t));

그런 다음 다음을 수행 할 수 있습니다.

delay(3000).then(() => console.log('Hello'));

reject예를 들어 eslint 유효성 검사와 같은 옵션 이 필요한 경우const delay = ms => new Promise((resolve, reject) => setTimeout(resolve, ms))
David Thomas

10

.then () 블록 안에 있고 settimeout () 을 실행하려는 경우

            .then(() => {
                console.log('wait for 10 seconds . . . . ');
                return new Promise(function(resolve, reject) { 
                    setTimeout(() => {
                        console.log('10 seconds Timer expired!!!');
                        resolve();
                    }, 10000)
                });
            })
            .then(() => {
                console.log('promise resolved!!!');

            })

출력은 아래와 같습니다.

wait for 10 seconds . . . .
10 seconds Timer expired!!!
promise resolved!!!

행복한 코딩!


-1

node.js에서 다음을 수행 할 수도 있습니다.

const { promisify } = require('util')
const delay = promisify(setTimeout)

delay(1000).then(() => console.log('hello'))

나는 이것을 시도하고 지연 함수 내에서 0이 예상되는 잘못된 인수 수를 얻었습니다.
Alex Rindone

node.js 8, 10, 12, 13에서 작동하는지 확인할 수 있습니다. 코드를 어떻게 실행하는지 확실하지 않지만 util폴리 필이 잘못 되었다고 가정 할 수 있습니다 . 번 들러 등을 사용하고 있습니까?
1
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.