2017-01-05 5 views
5

JS APIと対話しようとしましたが、Gruntタスクで実行すると失敗します。私の論理は混乱していると思う。私の手順:executor関数から約束を返しますか?

  • 彼らが古い場合
  • check_tokens)それらをチェックし、ファイルからトークンを取得する - それらをリフレッシュ(refresh_tokens
  • リフレッシュするコールAPIは、失敗した場合 - 新しいもの(authorize_with_api)<を取得します - これは

現在の兵卒タスクが報告authorize_with_apiから

  • がエラーで拒否またはトークンを解決する問題ですと完了しません。私がauthorize_with_apiへの呼び出しをコメントアウトすると、それはエラーで正しく終了し、私の最上位のcaught error!メッセージが表示されます。

    executor関数から約束を返せないのはなぜですか?私の論理に何が問題なの?約束解決しない約束コンストラクタ(またはその中の任意の関数)からの復帰

    /* global sdk, config, tokens */ 
    return getTokens().then((p_tokens) => { 
        tokens = p_tokens; 
        return check_tokens(tokens); 
    }).then((tokens) => { 
        console.log('then() is called!'); 
    }).catch((err) => { 
        console.error('caught error!', err); 
    }); 
    
    function check_tokens(tokens) { 
        if(are_old(tokens)) { // returns true 
         return refresh_tokens(tokens); 
        } 
        return Promise.resolve(tokens); 
    } 
    
    function refresh_tokens(tokens) { 
        return new Promise(function(resolve, reject) { 
         sdk.refreshTokens(tokens.refresh_token, function(err, new_tokens) { 
          if(err) { 
           if(error.code === 'invalid_grant') { 
            return authorize_with_api(); 
           } 
           reject('refreshTokens failed'); 
          } else if(newTokens) { 
           resolve(new_tokens); 
          } 
         }); 
        }); 
    } 
    
    function authorize_with_api() { 
        return new Promise(function(resolve, reject) { 
         sdk.getTokens(config.auth_code, function(err, tokens) { 
          if(err) { 
           reject('getTokens failed'); 
          } else if(tokens) { 
           resolve(tokens); 
          } 
         }); 
        }); 
    } 
    
  • +0

    '、あなたがそれを渡すことを意味するのですか?これを呼び出すgulpタスクを表示することは役に立ちます –

    +1

    あなた自身の約束をすることは避けてください。ライブラリはこのタスクを解決するために書かれており、そのうちの1つを使用します。たとえば、ブルーバードはあなたのためにそれを行うことができます。 http://bluebirdjs.com/docs/api/promise.promisifyall.html – Tomalak

    +1

    @Tomalakさらに詳しく説明できますか? OPはネイティブプロミスを使用していますか? –

    答えて

    8

    :あなたの代わりにsdk.refreshTokensコールバックからのリターンを持っていなかった場合でも

    return new Promise(function(resolve, reject) { 
        sdk.refreshTokens(..., function(err, new_tokens) { 
        if(error.code === 'invalid_grant') { 
         return authorize_with_api(); 
        } // ^--- this will not chain to the promise being created. 
    

    は直接ましたreturn authorize_with_api()コールバックなしでは、結果はまだチェーンされません。

    は約束を解決するには、代わりにその構築物から返すことはできませんが、明示的に指定したコールバックの1(決意/拒否)を呼び出す必要があります。

    return new Promise(function(resolve, reject) { 
        sdk.refreshTokens(..., function(err, new_tokens) { 
        if(error.code === 'invalid_grant') { 
         resolve(authorize_with_api()); 
        } // ^--- must call resolve here 
    

    を約束が実際に拒絶反応を扱うの解決にも関係なくので、もしauthorize_with_apiが解決または拒否すると、状態はそれに応じてチェーンの上に伝播します。

    私の提案はまだ早期復帰if分岐コンディショニングの意図したセマンティクスを維持するためにreturn文を維持することですが、reject/resolvePromises can only be resolved onceおよびすべてのさらなる呼び出しは無視されるので、コードはそれなしで動作します。

    return new Promise(function(resolve, reject) { 
        sdk.refreshTokens(..., function(err, new_tokens) { 
        if(error.code === 'invalid_grant') { 
         return resolve(authorize_with_api()); 
        } // ^--- should still return here for readability - clean logic purposes 
        reject('refreshTokens failed'); // this will be ignored if the above `resolve` gets called first, no matter if you have the `return` statement 
    

    例:

    function success() { 
     
        return Promise.resolve('success'); 
     
    } 
     
    
     
    function error() { 
     
        return Promise.reject('error'); 
     
    } 
     
    
     
    function alwaysPending() { 
     
        return new Promise(() => { 
     
        return success(); 
     
        }); 
     
    } 
     
    
     
    function resolves() { 
     
        return new Promise((resolve) => { 
     
        resolve(success()); 
     
        }); 
     
    } 
     
    
     
    function rejects() { 
     
        return new Promise((resolve) => { 
     
        resolve(error()); 
     
        }); 
     
    } 
     
    
     
    alwaysPending().then(console.log); // doesn't log anything 
     
    resolves().then(console.log); 
     
    rejects().catch(console.log);

    `` authorize_with_api内未定義ているように見えるtokens`
    +1

    優れた説明! _removes hat_ – montrealist

    +0

    仲間を助けてくれてうれしいです:) – nem035

    +0

    彼は 'Promise'エグゼキュータ関数からでも' return'するのではなく、その内部の非同期コールバックからも注目しています。 – Bergi

    関連する問題