在返回函数变量之前,如何等待诺言完成?


149

我仍在努力兑现承诺,但是由于这里的社区而取得了一些进展。

我有一个简单的JS函数,用于查询Parse数据库。它应该返回结果数组,但是显然由于查询的异步性质(因此,promise),该函数在结果之前返回,给我留下了未定义的数组。

我需要怎么做才能使此功能等待promise的结果?

这是我的代码:

function resultsByName(name)
{   
    var Card = Parse.Object.extend("Card");
    var query = new Parse.Query(Card);
    query.equalTo("name", name.toString());

    var resultsArray = [];

    var promise = query.find({
               success: function(results) {
               // results is an array of Parse.Object.
                             console.log(results);
                             //resultsArray = results;
                             return results;
               },

               error: function(error) {
               // error is an instance of Parse.Error.
                             console.log("Error");
               }
    });                           

}

3
您可能还考虑使用异步/等待。节点现在支持异步/ AWAIT开箱即用,因为7.6版本
Viliam SIMKO

Answers:


66

而不是返回一个resultsArray结果数组,而是返回一个对结果数组的promise,而不是返回一个then在调用站点上的promise-这具有调用者的额外好处,即知道该函数正在执行异步I / O。JavaScript中的编码并发性基于此-您可能需要阅读以下问题以获得更广泛的想法:

function resultsByName(name)
{   
    var Card = Parse.Object.extend("Card");
    var query = new Parse.Query(Card);
    query.equalTo("name", name.toString());

    var resultsArray = [];

    return query.find({});                           

}

// later
resultsByName("Some Name").then(function(results){
    // access results here by chaining to the returned promise
});

Parse自己的博客文章中,您可以看到更多将parse promise与查询一起使用的示例。


你能告诉我这是什么支持吗?IE9支持吗?
sandrina-p

是的,但是Parse本身已经死了,所以有@SandrinaPereira。这是解析代码。
本杰明·格伦鲍姆

1
嗯,这不仅是纯JavaScript吗?我一直在寻找一种方式来做到这一点(等功能完成启动另一个),但只使用纯JavaScript ..
sandrina-P

问题在于解析代码,而不是承诺。承诺可以在任何浏览器中(与库一起使用)。在IE6蓝鸟运行和Netscape 7
本杰明Gruenbaum

1
我已经读了两天了,但是仍然没有人解决这个问题。这个公认的答案彼此相同。该函数返回一个Promise,而不是OP请求的值。为什么将此答案标记为已接受?
iGanja

19

我需要怎么做才能使此功能等待promise的结果?

使用async/await(自2017年底起,ECMA6的不组成部分,但可用于Chrome,Edge,Firefox和Safari,请参见canIuse
MDN

    async function waitForPromise() {
        // let result = await any Promise, like:
        let result = await Promise.resolve('this is a sample promise');
    }

由于注释而添加:异步函数始终返回Promise,并且在TypeScript中看起来像:

    async function waitForPromise(): Promise<string> {
        // let result = await any Promise, like:
        let result = await Promise.resolve('this is a sample promise');
    }

4
如果在没有等待的情况下(或在非异步代码中)调用,异步函数仍将返回一个Promise对象。如果不确定,请检查console.log(waitForPromise())的结果。在async函数中检查console.log(result)打印出您期望的结果,但是从async函数返回的结果会立即发生而不会阻塞,并会返回一个promise。阻止javascript通常是非常糟糕的,因为它是一个单线程应用程序,而阻止将使其他所有发布/订阅客户端的通知饿死,这实际上会使整个应用程序屈服。
SRM

1
.net在“ promise”(如任务类)上具有.wait()。Javascript是否缺少此功能?我需要等待一些东西,然后退出节点命令行工具,该工具可能会将其输出传递给另一个工具。“等待”仅在异步函数中起作用。意味着它不能超出承诺的范围。
TamusJRoyce,

@SRM我觉得您的评论基于对样本的误解-它与“内部” Promise.resolve(作为最简单的Promise示例)有关,因此您在评论中没有外部调用者。因此,我决定更新答案。
Martin Meeser

@TamusJRoyce猜想这是一个问题,但是我认为在C#中,您可以使用Task.ContinueWith(Task),这与您在接受的答案中看到的想法相同(在这里称为“ then()”)。
Martin Meeser

我想我现在知道了。我几乎可以将整个脚本包装在一个巨大的异步函数中。并将该函数作为脚本的最后一行。该功能仍然是样板。但是比我以前想象的要少。我不习惯在函数内编写函数。谢谢@MartinMeeser!
TamusJRoyce,

3

您不想让函数等待,因为JavaScript旨在成为非阻塞的。而是在函数末尾返回promise,然后调用函数可以使用promise获取服务器响应。

var promise = query.find(); 
return promise; 

//Or return query.find(); 

1
您的整个回调功能success:已关闭。
本杰明·格林鲍姆

或更好:return query.find();
mash

还可以 我仅将其保留为说明目的,但将其添加为注释。
追踪

我试过了,但是结果似乎是不确定的。resultsByName(“ name”)。then(function(results){console.log(“ got array” + results.count);});
mac_55

1
谢谢,结果函数内部一定存在某种错误。现在正在工作。我将console.log更改为results.length,可以看到我返回的数组中有1个条目:)
mac_55

2

您实际上不是在这里使用诺言。解析允许您使用回调或承诺;你的选择。

要使用promise,请执行以下操作:

query.find().then(function() {
    console.log("success!");
}, function() {
    console.log("error");
});

现在,要在诺言完成后执行任务,您只需在then()调用内的诺言回调中执行它即可。到目前为止,这将与常规回调完全相同。

要真正利用承诺,就是将它们链接起来,如下所示:

query.find().then(function() {
    console.log("success!");

    return new Parse.Query(Obj).get("sOmE_oBjEcT");
}, function() {
    console.log("error");
}).then(function() {
    console.log("success on second callback!");
}, function() {
    console.log("error on second callback");
});

结果对象是什么类型的对象?因为它似乎不包含我的数组
mac_55

应该是的数组Parse.Object
mash
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.