是否保证可以兑现承诺?

时间:2019-08-02 18:38:18

标签: javascript node.js promise es6-promise

假设我们有一个名为logData的简单函数来处理HTTP请求。同样,假设我们还有另一个名为logIntoDatabase的函数。

async logIntoDatabase(message) { ... }

async logData(request, response) {
    await logIntoDatabase("something happened");
    response("log successful");
}

假定我们不必确定数据已记录到数据库中(我们不需要等待数据库的响应)。因此,我们进行了一些优化:

async logIntoDatabase(message) { ... }

async logData(request, response) {
    logIntoDatabase("something happened");
    response("log successful");
}

要执行logIntoDatabase绝对保证吗? (好像我们在等待它完成)

4 个答案:

答案 0 :(得分:1)

是的,只要调用它的函数(logIntoDatabase)也可以执行,就可以确定logData将要执行。

请注意,它不一定能按照您的预期做:它可能会引发错误或花费很长时间才能完全执行,尽管这是与函数内容有关的问题,而不是您要调用的函数synchronouslyasynchronously

答案 1 :(得分:1)

  

promise或异步内部的脚本将始终执行,除非   您的应用程序/服务器强制停止或崩溃。

您可以阅读有关异步工作原理的文章。脚本仍在堆栈中,但不阻止其他进程。

https://blog.bitsrc.io/understanding-asynchronous-javascript-the-event-loop-74cd408419ff

答案 2 :(得分:1)

  

保证履行承诺吗?

首先,这是一些术语的正确性,但是承诺不会“执行”。异步函数会执行,它们会创建承诺,以帮助您监视其完成情况。您不是在这里诺言。您正在调用一个返回承诺的函数。

  

绝对保证logIntoDatabase将要执行吗?

是的,如果调用了logData(...),那么在您的第一个和第二个代码示例中,logIntoDatabase()将始终作为该函数的第一行执行。

您的方法如下:

async logData(request, response) {
    await logIntoDatabase("something happened");
    response("log successful");
}

本质上等效于此(假定logIntoDatabase()返回一个promise并且不同步抛出):

logData(request, response) {
    return logIntoDatabase("something happened").then(() => {
        response("log successful");
    });
}

这样,您可以看到在logData()中执行的第一行是对logIntoDatabase()的调用。


async函数的完全替代品是这样:

logData(request, response) {
    try {
        return Promise.resolve(logIntoDatabase("something happened")).then(() => {
            response("log successful");
        });
    } catch(e) {
        return Promise.reject(e);
    }
}

这涵盖了其他不当行为,例如logIntoDatabase()不返回承诺或不同步抛出。但是,即使以这种更为完整的类比,您仍可以看到logIntoDatabase()仍然可以被调用。


在您的第二个代码示例中:

async logData(request, response) {
    logIntoDatabase("something happened");
    response("log successful");
}

您仍然可以保证会调用logIntoDatabase()。但是,这在行为上与您使用await的版本在三种方面有所不同:

    即使response("log successful")拒绝,也会始终调用
  1. logIntoDatabase()

  2. response("log successful")将在logIntoDabase()完成异步操作之前被称为。

  3. logData()返回的承诺与logIntoDatabase()是解决还是拒绝没有任何关系。如果logIntoDatabase()resolve("log successful")均不会同时引发,则将以undefined的解析值来解析承诺。如果其中一个同步抛出,那么从logData()返回的promise将被拒绝,但有一个例外,那就是拒绝的原因。

因此,您的第二个示例与此类似:

logData(request, response) {
    try {
        logIntoDatabase("something happened");
        response("log successful");
        return Promise.resolve();
    } catch(e) {
        return Promise.reject(e);
    }
}

而且,您可以看到logIntoDatabase()仍然可以保证始终被调用。

答案 3 :(得分:0)

是的!

JavaScript中的承诺就像现实生活中的承诺一样,一旦兑现承诺,就可以保证遵守。

希望这会有所帮助