如何在开始下一个功能之前等待功能完成?

Posted

技术标签:

【中文标题】如何在开始下一个功能之前等待功能完成?【英文标题】:How to wait for function finish before starting with next function? 【发布时间】:2020-06-18 08:36:27 【问题描述】:
const ytdl = require("ytdl-core");
exports.function1 = async () => 
  const result = await this.function2();
  if (!result) return console.log("result not found in function1");
;
exports.function2 = () => 
  return this.function3();
;
exports.function3 = () => 
  ytdl.getInfo(/*URL For any Youtube video*/, (error, result) => 
    if (error) return console.log(error);

    return info && console.log("found result in function3");
  );
;

我得到的输出是:

在函数 1 中找不到结果

在function3中找到结果

ytdl.getInfo 是一个函数,它获取 youtube 视频的 URL,并返回一个带有该视频信息的 json 对象的回调。 从这段代码中,我需要在继续之前将结果返回给 function1,所以我猜测使用 await 是最好的选择,但 await 不起作用(我猜测是因为它确实返回了 promise)。这里可以做些什么来让这个函数等待?

【问题讨论】:

您需要更清楚地了解您要完成什么以及您的代码没有完成什么。您的标题应该是一个简短的解释,并且在您的问题正文中,您需要对此进行扩展。 【参考方案1】:

您正在等待一个非异步函数。

看看这个函数声明。

exports.function2 = () => 

现在看看你是如何使用它的。

const result = await this.function2();

你看到问题了吗?如果不这样做,则您正在对非异步函数使用 await,或者换句话说,您没有等待函数完成。为了解决这个问题,您需要执行以下操作:

const ytdl = require("ytdl-core");

exports.function1 = async () => 
  const result = await this.function2();
  if (!result) return console.log("result not found in function1");
;

exports.function2 = async () => 
  return this.function3();
;

exports.function3 = () => 
  return new Promise((resolve, reject) => 
      ytdl.getInfo(/*URL For any Youtube video*/, (error, result) => 
        if (error) return reject(error);

        resolve(info && console.log("found result in function3"));
      );
  );

;

此外,请注意函数 3 现在返回了一个 Promise。您可以像上面提到的那样使用 promisify,但如果您不想这样做,则需要将 ytdl 调用包装在一个 Promise 中。在回调内部返回不会从父函数返回;最好使用promise或将回调函数传递给函数。

【讨论】:

要补充这一点,我鼓励您使用更具描述性的函数名称,但这显然不会改变功能。 感谢您的回复。它奏效了,结果证明我对承诺真的很糟糕。经过几次点击和试验,我的代码运行良好。【参考方案2】:

在其最终参数上使用通用模式(error, value) => 的回调函数可以被承诺。

const util = require('util');

然后

const pgetInfo = util.promisify(ytdl.getInfo);
let result = await pgetInfo(/*URL For any Youtube video*/);

const pgetInfo = util.promisify(ytdl.getInfo);
pgetInfo(/*URL For any Youtube video*/)
    .then((result) =>  /* result stuff */ )
    .catch((err) =>  /* err stuff */ );

【讨论】:

感谢您的解决方案,但我还没有使用它。但我将来会检查一下。不过这个方法看起来很简单。

以上是关于如何在开始下一个功能之前等待功能完成?的主要内容,如果未能解决你的问题,请参考以下文章

如何告诉 PowerShell 在开始下一个命令之前等待每个命令结束?

如何等待多个异步功能完成?

节点在继续之前等待异步功能

如何使 segue 等待功能在按钮按下时完成?

您如何等待主队列完成处理程序?

在使用 redux-observables 开始另一个史诗之前,如何等待不同的史诗完成并更新商店?