簡體   English   中英

從執行函數返回一個承諾?

[英]Return a promise from an executor function?

嘗試與JS API交互,但在Grunt任務運行時失敗; 我認為我的邏輯很困惑。 我的步驟:

  • 從文件中獲取令牌,檢查它們( check_tokens
  • 如果它們是舊的 - 刷新它們( refresh_tokens
  • 調用API刷新,如果失敗 - 獲取新的( authorize_with_api )< - 這是問題
  • 來自authorize_with_api拒絕錯誤或解決令牌

目前,Grunt任務報告UnhandledPromiseRejectionWarning並且永遠不會完成。 如果我注釋掉對authorize_with_api的調用,那么它會正確退出並出現錯誤,並且我得到了最頂層的caught error! 消息打印。

為什么我不能從執行函數中返回一個承諾? 我的邏輯出了什么問題?

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

從Promise構造函數(或其中的任何函數)返回並不能解析承諾:

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.

即使你沒有從sdk.refreshTokens回調中獲得返回,而是直接return authorize_with_api()而沒有回調,結果仍然不會被鏈接。

要解析promise,您不能從其構造函數返回,但必須顯式調用其中一個給定的回調(resolve / reject):

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

解決一個promise實際上也會處理拒絕,所以無論authorize_with_api解析或拒絕,狀態都會相應地向上傳播。

我的建議是仍然保持return語句以保持if分支條件的預期可視語義早期返回,但代碼將在沒有它的情況下工作,因為Promises只能被解析一次並且所有進一步的reject / resolve調用都被忽略。

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

只要寫下最后的if語句:

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);
            } else {
                reject('tokens == undefined && err == undefined');
            }
        });
    });
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM