1. ホーム
  2. javascript

[解決済み] プロミスチェーンでsetTimeoutを使用する

2022-03-08 23:35:13

質問

最初のリクエストでリンクのセットを取得し、次のリクエストで最初のリンクのコンテンツを取得します。しかし、私は次のプロミスオブジェクトを返す前に遅延を作りたいので、私はそれにsetTimeoutを使用します。しかし、それは私に次のJSONエラーを与える( without setTimeout() it works just fine )

SyntaxError: JSON.parse: 予期しない文字が1行目1列目にあります。 JSONデータ

なぜ失敗するのか知りたいのですが?

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);
});

解決方法は?

プロミスの連鎖を維持するために setTimeout() からプロミスを返すわけではないので、今までのように .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メソッドを追加し、直接 .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);
});

または ブルーバードプロミスライブラリ これは、すでに .delay() メソッドが組み込まれています。