草庐IT

javascript - 从执行函数返回 promise ?

coder 2024-07-29 原文

尝试与 JS API 交互,但在由 Grunt 任务运行时失败;我觉得我的逻辑很困惑。我的步骤:

  • 从文件中获取 token ,检查它们 (check_tokens)
  • 如果它们是旧的 - 刷新它们(refresh_tokens)
  • 调用 API 刷新,如果失败 - 获取新的 (authorize_with_api) <->
  • 来自 authorize_with_api 错误拒绝或使用 token 解决

目前 Grunt 任务报告一个 UnhandledPromiseRejectionWarning 并且永远不会完成。如果我注释掉对 authorize_with_api 的调用,它会正确退出并出现错误,并且我会打印最上面的 caught error! 消息。

为什么我不能从执行函数中返回一个 promise ?我的逻辑有什么问题?

/* 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 构造函数(或其中的任何函数)返回并不会解析 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 ,您不能从其构造函数返回,而必须显式调用给定回调之一(解决/拒绝):

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 can only be resolved once 和所有对 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);

关于javascript - 从执行函数返回 promise ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41488363/

有关javascript - 从执行函数返回 promise ?的更多相关文章

  1. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  2. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  3. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  4. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

  5. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  6. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  7. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  8. ruby - 为什么 Ruby 的 each 迭代器先执行? - 2

    我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试

  9. ruby - Ruby 中的隐式返回值是怎么回事? - 2

    所以我开始关注ruby​​,很多东西看起来不错,但我对隐式return语句很反感。我理解默认情况下让所有内容返回self或nil但不是语句的最后一个值。对我来说,它看起来非常脆弱(尤其是)如果你正在使用一个不打算返回某些东西的方法(尤其是一个改变状态/破坏性方法的函数!),其他人可能最终依赖于一个返回对方法的目的并不重要,并且有很大的改变机会。隐式返回有什么意义?有没有办法让事情变得更简单?总是有返回以防止隐含返回被认为是好的做法吗?我是不是太担心这个了?附言当人们想要从方法中返回特定的东西时,他们是否经常使用隐式返回,这不是让你组中的其他人更容易破坏彼此的代码吗?当然,记录一切并给出

  10. ruby - 检查是否通过 require 执行或导入了 Ruby 程序 - 2

    如何检查Ruby文件是否是通过“require”或“load”导入的,而不是简单地从命令行执行的?例如:foo.rb的内容:puts"Hello"bar.rb的内容require'foo'输出:$./foo.rbHello$./bar.rbHello基本上,我想调用bar.rb以不执行puts调用。 最佳答案 将foo.rb改为:if__FILE__==$0puts"Hello"end检查__FILE__-当前ruby​​文件的名称-与$0-正在运行的脚本的名称。 关于ruby-检查是否

随机推荐