使用 Promise 设置变量以获取回调函数的返回值

11

我得到了“对象”值而不是准确的值。如何使用回调函数获取返回的值?

function loadDB(option, callBack){
    var dfd = new jQuery.Deferred(),
        db = window.openDatabase('mydb', '1.0', 'Test DB', 1024*1024),
        selectQuery = "SELECT log FROM LOGS WHERE id = ?";
    db.transaction(function(tx){
        tx.executeSql(selectQuery,[option],function(tx,results){
            var retval;
            if( results.rows.length ) {
                retval = unescape(results.rows.item(0)['log']);
            }
            var returnValue = dfd.resolve(retval);
        });
    });
    return dfd.promise();
}
results = loadDB(2).then(function(val){ return val; } );
console.log("response***",results);
2个回答

43

一个Promise就像是一个封闭的盒子:

enter image description here

你上面使用deferred对象的代码,创建了一个盒子,并告诉你在未来的某个时刻可以打开它。那个时刻是当上面的代码调用.resolve方法时。

当你执行 results = loadDB(2) 时,你把“一个盒子”放到了results里。

Promise还有一个方法可以打开盒子、处理值并返回一个新的盒子(也会一路打开任何附加的盒子)。这个方法就是.then

用盒子来解释:

enter image description here =>( open. => e) => e

也就是说,它接收盒子,打开它并应用一个函数对其中的值进行操作,然后返回另一个带有新值的盒子。

因此,如果你想处理这个值,你需要在唯一打开盒子的地方挂接上去,就像Bergi建议的那样:

loadDB(2).then(function(val){
    console.log("response***", val);
}); // this also returns a promise btw

实际上,被应用的函数不需要打开盒子本身,它只需要呈现值即可。 - Bergi
以上符号表示什么?从某种意义上说,它就像一个单子 - 它接受一个盒子(即this)和一个接受开放盒子并返回封闭盒子的函数 - 并在第二个值上返回封闭盒子 - 更正式地说(忽略递归同化)(M t)→(t→M u)→(M u) @Bergi - Benjamin Gruenbaum
是的,但是图片下面的句子不是 :-) 另外,我更愿意把它改为“盒子的内容”,而不是“打开盒子”,那样听起来就像 M t -> (OpenM t -> M u) -> M u - Bergi
啊,那么这些图片有歧义 - 开放的盒子本应代表值本身是可访问的。 :) - Benjamin Gruenbaum
这个问题可以通过执行 console.log(await loadDB(2)) 来解决吗?这种方法可行吗? - Brentspine
@Brentspine 是的 - Benjamin Gruenbaum

8

在 Promise(异步)上下文中,您无法获取解析值。

相反,您需要将 console.log 调用和其他依赖它的内容 移入 Promise 上下文中:

loadDB(2).then(function(val){
    console.log("response***", val);
});

@dystroy,这是“JavaScript中的异步并发如何工作”的问题 - 这些问题很常见,而且它们将继续存在。这是一个合理的问题,Bergi的答案很好 :) - Benjamin Gruenbaum
@BenjaminGruenbaum 当然这是一个好答案。我只是想知道我们是否应该链接到大型常见问题解答集。 - Denys Séguret

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接