【问题标题】:async function equivalent of a Promise等效于 Promise 的异步函数
【发布时间】:2018-11-27 00:25:11
【问题描述】:

我有一个返回 promise 的函数,如下所示:

let aFunction= function(){
    return new Promise((resolve, reject){
       someNodeApi(params, function(err, data)) {
          if(err) {
            return reject(err);
          }
          if(data meets certain criteria) {
             someOtherNodeApi(params, function(err, data)) {
                // handle conditions.
             }
          }
          resolve(data);
       }         
    })
}

我想要一个async 函数等价于这种函数。简而言之,我需要这样的东西:

let aFunction = async function(){
   someNodeApi(params, function(err, data){
      if(err) {
          // reject condition
      }
      // resolve condition.
   })
}

那么rejectresolve 上面的条件应该是什么,以便我调用函数的所有地方都像这样:

aFunction()
  .then(data=>{})
  .catch(err=>{})

应该是不变的。

编辑

我必须澄清一下,我的问题不是关于如何调用异步函数。但它是关于如何转换一个返回 Promise 的函数,以便能够使用 async-await 模式的优点,而无需修改其调用方式。 (处理预 async-await 时代节点 js 代码时非常常见的场景)。

【问题讨论】:

  • 你的前提是错误的。异步函数的调用方式不同 (var result = await foo())。如果你想保持 then catch 模式,你需要继续使用 Promise。这让我想到了一个重要的问题:为什么你想摆脱承诺?
  • @ChrisG 我想摆脱承诺,原因与为什么将 async-await 添加到节点 js 中的原因相同。这是一种更好的方式,更像是同步编程。
  • 编辑后,您的问题似乎也是。我如何承诺一个 api,或者我如何使用 async/await。如果是第一个,请使用库。如果是第二个,请阅读文档:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • @MattWay 本质上是一个异步函数返回一个 Promise。因此,以某种方式使用 async/await 成为选择和意见的问题。所以我不认为我的问题是关于如何使用它。
  • 如果你的问题是how to convert a function that returns a Promise to be able to use the goodness of async-await pattern without having to modify the way its called,那么据我所知,答案是“你不能”。另外,据我从您的 cmets 收集到的信息,您确实询问如何使用 async / await 因为如果您知道,这个问题就不存在了。 essentially an async function returns a Promise 不,它没有。

标签: javascript node.js promise async-await


【解决方案1】:

这就是我喜欢写 async/await 的方式,它非常简单。里面的所有代码都可以读取为同步。 编辑:只有当 API 返回一个已解决或被拒绝的 Promise 对象时,await 才会起作用。 await 不解决承诺。

function someAPI() {
    return new Promise((resolve, reject)=>{
      someNodeApi(params, function(err, data){
            if(err) {
                reject(error)
            } else {
              resolve(data)
            }
            // resolve condition.
        })
    });
  }


async function aFunction() {
  try {
    const result = await someAPI();
    return result;
  } catch(err){
    console.log(err);
  }
}

aFunction()
.then((res) => console.log(res))

【讨论】:

  • 我认为这是一个很好的答案!这确实回答了我的疑问。简而言之,我们必须在异步函数中的任何地方都使用 await。
  • 这行不通,因为@rahulserver 的 api 还没有被承诺。
  • @MattWay 你是对的。但我可以使用 utils.promisify 进行转换。从概念上讲,这个答案解决了我的问题。但是,值得编辑答案以包括该功能需要被承诺
  • @rahulserver 如果您使用有前途的库,那么这个答案是完全多余的。正如我在回答中所说,您根本不需要函数。
  • 是的,你的API需要返回一个promise,我会编辑给你看。
【解决方案2】:

当更改为 async/await 时,更改的不是您的 Promise 设置,而是您如何调用您的 Promise。例如:

aFunction()
  .then(data=>{})
  .catch(err=>{})

// becomes
try{
  const data = await aFunction()
}catch(err){
  // do something with err
}

请记住,使用 await 的函数需要设置为async


如果您的someNodeApi 调用已经为promise 设置,那么结果仍将完全相同,您根本不需要aFunction。例如,如果你在你的 api 上使用了一个有前途的库,那么你根本不需要aFunction

someNodeApi(params)
  .then(data => {})
  .catch(err => {})

// or

const data = await someNodeApi(params)
if(data meets certain criteria) {
   const otherData = someOtherNodeApi(params)
}

【讨论】:

  • 谢谢@Matt。当然看起来不错。但是,如果您要在该异步函数中使用大量 api 调用(基于回调),您会怎么做?我的意思是我只想让函数内部的代码更像是同步的。简而言之,如果节点语法允许,我将在基于 promise 的函数中使用 await 关键字,而不使用异步。
【解决方案3】:

Snippet1 : 这里可以看到async-await的用法

let fn = async function(a) {
	let val = 10;
	return new Promise((resolve, reject) => {
		if(a > val) {
			resolve("+++++Resolved");
		}
		else {
			reject("++++++Rejected")
		}
	})
};

(async () => {
	try {
		let result1 = await fn(20);
		console.log(result1);

		let result2 = await fn(5);
		console.log(result2);
	}
	catch(err) {
		console.error(err);
	}
    
})();

Snippet2 :在这里您可以看到使用 .then.catch 不会损害或破坏您的任何代码。

let fn = async function(a) {
	let val = 10;
	return new Promise((resolve, reject) => {
		if(a > val) {
			resolve("+++++Resolved");
		}
		else {
			reject("++++++Rejected")
		}
	})
};

fn(20).then(response => {
	console.log(response);
});

fn(5)
	.then(response => {
		console.log(response);
	})
	.catch(err => {
		console.error(err);
	})

如果您在返回异步函数的 Promise 上使用 fn().then.catch 模式,它不会破坏您的代码。
然而,使用 await 使它更优雅。

请随意参考我写的关于基础知识的详细文章 async-await 以及为什么 async-await 与 .then.catch 模式相比,优点 和这里的缺点:https://github.com/cskru/asyncAwaitSimplified

我已包含代码 sn-ps,您可以直接复制粘贴并试用。

PS:我在上面的 sn-ps 中使用了 async IIFE。
这是因为只能在异步函数/上下文中进行等待。

我还建议您查看此article 以获得 async-await 的坚实基础。

学习愉快!

干杯,
克鲁西卡

【讨论】:

    猜你喜欢
    • 2020-03-24
    • 1970-01-01
    • 1970-01-01
    • 2021-02-15
    • 1970-01-01
    • 1970-01-01
    • 2017-10-24
    • 1970-01-01
    相关资源
    最近更新 更多