从承诺返回 then()

Posted

技术标签:

【中文标题】从承诺返回 then()【英文标题】:Return from a promise then() 【发布时间】:2016-03-09 18:25:18 【问题描述】:

我有一个这样的 javascript 代码:

function justTesting() 
  promise.then(function(output) 
    return output + 1;
  );


var test = justTesting();

我总是得到一个未定义的 var 测试值。我认为这是因为承诺尚未解决。有一种方法可以从承诺中返回值吗?

【问题讨论】:

then() 调用的返回值又是一个承诺,它包装了您返回的值。 test 未定义,因为 justTesting 在您的示例中不返回任何内容(您没有返回)。添加一个 return 和 test 将被定义为一个承诺。 变量promise是什么。您没有在任何地方显示它的定义,也没有从您的 justTesting() 函数返回任何内容。如果您需要更好的帮助,您需要描述您要解决的问题,而不是仅仅向我们展示那些“离题”甚至无法说明您真正想要做什么的代码。解释您要解决的问题。 具有讽刺意味的是,每个答案都告诉我们如何返回另一个要调用的承诺。 实际答案: softwareengineering.stackexchange.com/a/350041/171994 【参考方案1】:

要使用 Promise,您必须调用一个创建 Promise 的函数,或者您必须自己创建一个。你并没有真正描述你真正想要解决的问题,但这里是你自己创建承诺的方式:

function justTesting(input) 
    return new Promise(function(resolve, reject) 
        // some async operation here
        setTimeout(function() 
            // resolve the promise with some value
            resolve(input + 10);
        , 500);
    );


justTesting(29).then(function(val) 
   // you access the value from the promise here
   log(val);
);

// display output in snippet
function log(x) 
    document.write(x);

或者,如果您已经有一个返回 Promise 的函数,您可以使用该函数并返回它的 Promise:

// function that returns a promise
function delay(t) 
  return new Promise(function(resolve) 
    setTimeout(function() 
      resolve();
    , t);
  );


function justTesting(input) 
  return delay(100).then(function() 
    return input + 10;
  );


justTesting(29).then(function(val) 
  // you access the value from the promise here
  log(val);
);

// display output in snippet
function log(x) 
  document.write(x);

【讨论】:

让我失望的是双倍的return,即justTesting 表示return.then => return。我知道这是可行的,因为我已经实现了这个(bcs linting 迫使我远离new Promise),但是你能解释一下如何理解/思考那个返回/返回对吗? @RonRoyston - 首先,你传递给.then() 的函数是一个独立于包含函数的函数,所以当它被调用时,它有自己的返回值。其次,来自.then() 处理程序的返回值成为promise 的解析值。因此,.then(val => return 2*val;) 将解析值从 val 更改为 2*val 解释得很漂亮,伙计。谢谢。【参考方案2】:

当您从then() 回调中返回某些内容时,这有点神奇。如果您返回一个值,则使用该值调用下一个 then()。但是,如果您返回类似 Promise 的内容,则下一个 then() 会等待它,并且仅在该 Promise 解决(成功/失败)时调用。

来源:https://web.dev/promises/#queuing-asynchronous-actions

【讨论】:

似乎是因为这个原因,然后我可以在***.com/q/53651266/2028440中同步使用Ajax请求迭代数组的promise链 相关link 但是 Promise.all 如何捕获每个已解决的承诺的返回值?【参考方案3】:

我在这里所做的是我从 justTesting 函数返回了一个承诺。函数解析后就可以得到结果了。

// new answer

function justTesting() 
  return new Promise((resolve, reject) => 
    if (true) 
      return resolve("testing");
     else 
      return reject("promise failed");
   
 );


justTesting()
  .then(res => 
     let test = res;
     // do something with the output :)
  )
  .catch(err => 
    console.log(err);
  );

希望这会有所帮助!

// old answer

function justTesting() 
  return promise.then(function(output) 
    return output + 1;
  );


justTesting().then((res) => 
     var test = res;
    // do something with the output :)
    

【讨论】:

如果在“//do something with the output”中添加return语句会发生什么?例如:我会在父函数中有“JustTesting().then...”。我可以在“then”部分返回一个值吗? 如果你想从 //do something 输出返回一个值,你必须在 justTesing() 之前添加一个 return。例如, " return justTesting().then((res) => return res; ); 好吧,这就是我的预期,我只是想确认一下 :) 谢谢!【参考方案4】:

我更喜欢使用“await”命令和异步函数来摆脱对承诺的混淆,

在这种情况下,我会先编写一个异步函数, 这将被用来代替这个问题的“promise.then”部分下调用的匿名函数:

async function SubFunction(output)

   // Call to database , returns a promise, like an Ajax call etc :

   const response = await axios.get( GetApiHost() + '/api/some_endpoint')

   // Return :
   return response;


然后我会从主函数调用这个函数:

async function justTesting() 
   const lv_result = await SubFunction(output);

   return lv_result + 1;

注意我在这里将主函数和子函数都返回给异步函数。

【讨论】:

对...使用 await 使它更清洁并解决了问题 完美,但是如果服务失败了怎么办?它会返回承诺吗? 嗨@minigeek,你应该在TRY-CATCH块之间放置await命令,如下所示:try const lv_result = await SubFunction(output); catch (error) console.log("读取图像时出错", error); 它试过了,但没用,所以我最终自己返回了 promise 哈哈【参考方案5】:

Promises 不“返回”值,它们将它们传递给回调(您使用 .then() 提供)。

它可能试图说你应该在承诺实现中执行resolve(someObject);

然后在您的then 代码中,您可以引用someObject 来做您想做的事情。

【讨论】:

【参考方案6】:

在解决 promise 后你不能返回值。而是在 promise 解决时调用另一个函数:

function justTesting() 
    promise.then(function(output) 
        // instead of return call another function
        afterResolve(output + 1);
    );


function afterResolve(result) 
    // do something with result


var test = justTesting();

【讨论】:

you cannot return a value after resolving a promise. 这不是真的,见javascript.info/promise-chaining,这里有一个更准确的答案(***.com/a/45482610/1681445)见// old answer最后一节代码【参考方案7】:

您需要使用数组或对象等引用数据类型。

function foo(u,n)
  let result = [];
  const userBrands = new Promise((res, rej)=> 
                        res(['brand 1', 'brand 3']);
                      )
  
  userBrands.then((ub)=>
    return new Promise((res, rej) =>
      res([...ub, 'brand 4', 'brand 5']);
    )
  ).then(response => 
    return result.push(...response);
  );
  return result;
;
foo();

【讨论】:

【参考方案8】:

我认为原始发布者想要的是从一个承诺中返回一个未包装的值而不实际上返回另一个承诺。除非另有证明,否则恐怕这在 then() 或 async/await 上下文之外是不可能的。无论如何,你总能得到承诺。

【讨论】:

以上是关于从承诺返回 then()的主要内容,如果未能解决你的问题,请参考以下文章

Vue 从承诺中返回

Node.js 从函数返回一个承诺

then() 真的在所有情况下都返回一个承诺吗? [复制]

使用 Async 和 .then 承诺

执行 .Then() 承诺 NodeJS

链接承诺不会将数据从一个 .then 传递到下一个