Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 需要澄清承诺和异步/等待_Javascript_Node.js_Async Await - Fatal编程技术网

Javascript 需要澄清承诺和异步/等待

Javascript 需要澄清承诺和异步/等待,javascript,node.js,async-await,Javascript,Node.js,Async Await,我一直在使用Promises和async/await,它们几乎是一样的,对吗?通常我会做的是把我的承诺包装起来,然后归还 function someFetchThatTakesTime(){ // Promisify the request. return new Promise((resolve, reject) => { if(allGood){ resolve(); }else{ reje

我一直在使用Promises和async/await,它们几乎是一样的,对吗?通常我会做的是把我的承诺包装起来,然后归还

function someFetchThatTakesTime(){
    // Promisify the request.
    return new Promise((resolve, reject) => {
        if(allGood){
            resolve();
        }else{
            reject();
    });
}
然后我可以做:

someFetchThatTakesTime()
    .then(console.log('all good.')
    .catch(console.log('some error occured.');
或者我可以:

async function wrapMyFetch() {
    try {
        // Make the async call.
        data = await someFetchThatTakesTime();
        return data;
    } catch(err) {
        // Propagate the exception up stream.
        throw err;
    }
}

(async () => {
  let response = await wrapMyFetch();
  // Do stuff with the response.
})();
我想,到目前为止还很清楚

然而,我最近遇到了这样的情况:我的应用程序不关心等待结果被获取和数据容器被更新等。假设有一个更大的循环无限运行,任何承诺的请求都会在应用程序运行时填补空白

在这种情况下,我们真的不需要异步/等待模式,对吗?我们只想随着我们的循环前进,石头将落在我们身后的适当位置,无论它们是否准备好落在适当的位置,以防出现错误

我想澄清一下:async/await只会迫使事情线性运行,对吗?但是,如果我们不想要线性,并且我们可以接受衍生任务——承诺——在我们恢复运行周期的某个时候在后台完成任务,那么我们不需要异步/等待模式吗?对吗

我一直在使用Promises和async/await,它们几乎是一样的,对吗

嗯,async/await是建立在承诺之上的有用语法。Async/await依赖于承诺才能工作。所以,我不会把它们称为相同的东西,但是您可以用try/catch和.then.catch包围的wait编写功能相同的代码。你可以用任何一种。这两种方法都依赖于承诺

然而,我最近遇到了这样的情况:我的应用程序不关心等待结果被获取和数据容器被更新等。假设有一个更大的循环无限运行,任何承诺的请求都会在应用程序运行时填补空白

在这种情况下,我们真的不需要异步/等待模式,对吗?我们只想随着我们的循环前进,石头将落在我们身后的适当位置,无论它们是否准备好落在适当的位置,以防出现错误

没有规则要求打电话的人必须注意返回的承诺,或者在继续执行任务之前必须等待承诺。因此,如果您想让石头像您所说的那样落在背景中,并且适合您的应用程序,您可以这样编写代码

这通常被称为fire-and-forget编码,在这里,您启动了一些异步操作,这些操作将自己完成一些事情,您不需要注意它何时完成或是否出错,因为这对调用代码没有影响

但是,有一条规则,你不能让拒绝的承诺不经处理。因此,如果您要返回一个承诺,而调用方不打算对其做任何处理,那么您必须确保任何拒绝都由操作本身使用.catch进行处理,以便唯一返回的是已解决的承诺。即使你所做的只是注意到错误而不做任何处理,你也必须抓住错误

我一直在使用Promises和async/await,它们几乎是一样的,对吗

嗯,async/await是建立在承诺之上的有用语法。Async/await依赖于承诺才能工作。所以,我不会把它们称为相同的东西,但是您可以用try/catch和.then.catch包围的wait编写功能相同的代码。你可以用任何一种。这两种方法都依赖于承诺

然而,我最近遇到了这样的情况:我的应用程序不关心等待结果被获取和数据容器被更新等。假设有一个更大的循环无限运行,任何承诺的请求都会在应用程序运行时填补空白

在这种情况下,我们真的不需要异步/等待模式,对吗?我们只想随着我们的循环前进,石头将落在我们身后的适当位置,无论它们是否准备好落在适当的位置,以防出现错误

没有规则要求打电话的人必须注意返回的承诺,或者在继续执行任务之前必须等待承诺。因此,如果您想让石头像您所说的那样落在背景中,并且适合您的应用程序,您可以这样编写代码

这通常被称为fire-and-forget编码,在这里,您启动了一些异步操作,这些操作将自己完成一些事情,您不需要注意它何时完成或是否出错,因为这对调用代码没有影响

但是,有一条规则,你不能让拒绝的承诺不经处理。因此,如果您要返回一个承诺,而调用方不打算对其做任何处理,那么您必须确保任何拒绝都由操作本身使用.catch进行处理,以便唯一返回的是已解决的承诺。即使你所做的只是注意到 你必须抓住错误,而不去做任何事情

async/await只会强制事情线性运行,对吗

不是全局性的,不是。wait使它所使用的异步函数中的代码等待您传递给它的承诺解决,但这只影响您在其中使用它的函数,而不影响调用该函数的任何内容

异步函数是编写返回承诺的函数的语法糖。等待是消费承诺的语法糖。总之,它们极大地简化了承诺的使用,特别是通过使拒绝错误自动通过调用树传播

更具体地说,异步函数同步运行其代码,直到第一次等待或返回,或者直到代码从函数末尾运行,此时它返回一个承诺。然后,它的逻辑等待着承诺的解决,并继续下去;最终,它会根据它等待或返回的最后一个承诺发生了什么来解决它的承诺,或者在代码执行结束时使用未定义的代码来实现它

如果您不想等待承诺兑现,那么就不必等待,即使在异步函数中也是如此。只是不要用等待。例如,假设我们有这个fetch包装器,它为我们获取JSON并修复API footgun:

async function fetchJSON(...args) {
    const response = await fetch(...args);
    if (!response.ok) {
        throw new Error("HTTP error " + response.status);
    }
    return response.json();
}
下面是一个异步函数,它使用它执行初始查询以获取要获取的内容列表,然后并行获取所有这些内容:

async function fetchList(listUrl) {
    const list = await fetchJSON(listUrl);
    return Promise.all(list.map(item => fetchJSON(itemUrl)));
}
注意fetchList如何使用wait来等待要获取的内容列表,但不等待项目;它只是从promise.all返回它开始获取的项目列表的promise

还要注意fetchJSON中的wait如何使fetchJSON的逻辑等待fetch承诺解决,但不会使调用fetchJSON的调用方等待,除非调用方使用wait。fetchList只等待第一次调用以获取列表,而不等待列表中的项目

async/await只会强制事情线性运行,对吗

不是全局性的,不是。wait使它所使用的异步函数中的代码等待您传递给它的承诺解决,但这只影响您在其中使用它的函数,而不影响调用该函数的任何内容

异步函数是编写返回承诺的函数的语法糖。等待是消费承诺的语法糖。总之,它们极大地简化了承诺的使用,特别是通过使拒绝错误自动通过调用树传播

更具体地说,异步函数同步运行其代码,直到第一次等待或返回,或者直到代码从函数末尾运行,此时它返回一个承诺。然后,它的逻辑等待着承诺的解决,并继续下去;最终,它会根据它等待或返回的最后一个承诺发生了什么来解决它的承诺,或者在代码执行结束时使用未定义的代码来实现它

如果您不想等待承诺兑现,那么就不必等待,即使在异步函数中也是如此。只是不要用等待。例如,假设我们有这个fetch包装器,它为我们获取JSON并修复API footgun:

async function fetchJSON(...args) {
    const response = await fetch(...args);
    if (!response.ok) {
        throw new Error("HTTP error " + response.status);
    }
    return response.json();
}
下面是一个异步函数,它使用它执行初始查询以获取要获取的内容列表,然后并行获取所有这些内容:

async function fetchList(listUrl) {
    const list = await fetchJSON(listUrl);
    return Promise.all(list.map(item => fetchJSON(itemUrl)));
}
注意fetchList如何使用wait来等待要获取的内容列表,但不等待项目;它只是从promise.all返回它开始获取的项目列表的promise


还要注意fetchJSON中的wait如何使fetchJSON的逻辑等待fetch承诺解决,但不会使调用fetchJSON的调用方等待,除非调用方使用wait。fetchList只等待第一次调用以获取列表,而不等待列表中的项。

对,但不要忘记处理.catch中的错误。对,但不要忘记处理.catch中的错误。是的,比方说,调用方不会像您所说的那样对结果做任何处理。这个过程将更新一些db条目,如果失败,我们将在某个地方切换一些错误标志,但我们已经在运行时向前移动了。因此,可以说可以使用.then.catch.finally模式,我们不需要异步/等待模式?@mbilyanov-当然,没有人说过必须使用异步/等待。在语言中实现async/await之前,我们使用异步操作进行编程。只要确保你抓住了所有的拒绝。没有规则要求打电话的人必须注意回复的承诺,或者在继续他们的任务之前必须等待。用一个例子来说明这一点,你可以考虑日志记录。在磁盘上写入数据时,这应该需要时间,但实际上您可能不想等待。因此,您可以执行一个日志请求,该请求将在以后完成,您不需要真正停止并等待它完成。使用健壮的日志记录,您不会期望出现问题,如果存在问题,那么您可能不会有问题。那里
很可能是更大的错误。@VLAZ-是的,这是一个很好的例子。我有时在关闭文件时也会使用fire和forget。如果关闭文件时出错,尤其是在仅读取文件时,那么除了记录错误之外,您实在无法进行任何恢复。是的,比方说,调用方不会像您所说的那样对结果进行任何处理。这个过程将更新一些db条目,如果失败,我们将在某个地方切换一些错误标志,但我们已经在运行时向前移动了。因此,可以说可以使用.then.catch.finally模式,我们不需要异步/等待模式?@mbilyanov-当然,没有人说过必须使用异步/等待。在语言中实现async/await之前,我们使用异步操作进行编程。只要确保你抓住了所有的拒绝。没有规则要求打电话的人必须注意回复的承诺,或者在继续他们的任务之前必须等待。用一个例子来说明这一点,你可以考虑日志记录。在磁盘上写入数据时,这应该需要时间,但实际上您可能不想等待。因此,您可以执行一个日志请求,该请求将在以后完成,您不需要真正停止并等待它完成。使用健壮的日志记录,您不会期望出现问题,如果存在问题,那么您可能不会有问题。很可能有更大的错误。@VLAZ-是的,这是一个很好的例子。我有时在关闭文件时也会使用fire和forget。如果关闭文件时出错,尤其是仅从文件中读取时,那么除了记录错误之外,您实在无法进行任何恢复。因此,示例中的下一个阶段将是:fetchList['aaa','bbb','ccc'].then.catch?@mbilyanov-除非您是从异步函数或在顶级WAIT到达后在模块的顶级使用它,否则是的:-因此,示例中的下一个阶段将是:fetchList['aaa'、'bbb'、'ccc']。然后。catch?@mbilyanov-除非您是从异步函数使用它,或者在顶级wait到达后在模块的顶级使用它,否则是的:-