如何在 Promise 对象已解决后获取值

11

请注意,这只是一个刻意编造的例子。

    function longFunc(){
        var deferred = $.Deferred();

        setTimeout(function(){
            console.log("long func completed");
            deferred.resolve("hello");
        }, 3000);

        return deferred.promise();
    }

    function shortAfterLongFunc(x){
        console.log('short func completed with value: ' + x);
        return {
            a: x
        };
    }

processFurther(longFunc().then(shortAfterLongFunc)); // send the array for further processing

问题

我无法弄清楚在shortAfterLongFunc完成后如何返回任何类型的对象/函数以供下游进一步处理。我可以从shortAfterLongFunc中使用console.log,但这不是我要求的。 此处有演示代码

谢谢您的关注!

更新:

好的,只是为了让我的问题更好一些......我正在看一个简单的用例:

$.map(['H','E','L','L', 'O'], somefunc). // for each item in array apply somefunc function

function somefunc(x){ // gets called for each value 'H', 'E' etc. in the array by $.map()
    var longfunc = function(y){
        var deferred = $.Deferred();

        setTimeout(function(){
            console.log("long func completed");
            deferred.resolve(y.toLocaleLowerCase());
        }, 3000);

        return deferred.promise();
    };

    var shortAfterLongFunc = function(x){
        console.log('short func completed with value: ' + x);
        return x;
    }

    // What should I do here
    return longFunc(x).then(shortAfterLongFunc); // must return lower case char to the caller of someFunc

}

somefunc() 假设将数组中的每个元素转换为小写。但是,假设此处理需要很长时间且异步执行(想到setTimeout)...因此需要使用 Promise 以确保每个元素同步运行...但是在使用 Promise 后,我发现自己无法返回转换后的值。

2个回答

10

只需链接另一个then调用,因为shortAfterLongFunc返回新的promise,您可以继续使用它:

longFunc().then(shortAfterLongFunc).then(function(data) {
    console.log('all is complted', data);
});

演示:http://jsfiddle.net/ebt4pxxa/2/


1
当我有一个将代码包装在内的someFunc函数时,如何从promise中获取data值... function someFunc(){longFunc().then(shortAfterLongFunc).then(function(data) { console.log('all is complted', data); }); // 当有人调用someFunc()时,我想返回data} - Vikram
5
这个函数无法返回数据。这不是同步代码,因此您不能直接从中返回结果。您应该返回 Promise 对象并使用它。function someFunc() { return longFunc().then(...); }; var pr = someFunc(); pr.then(function(data) { console.log(data) });。返回 Promise 对象,将其分配给变量,传递并使用其 then 方法来访问已解析的数据。 - dfsq
当点击“运行”时,小提琴没有产生任何输出。 - David Spector
1
@DavidSpector 你有检查控制台吗? - dfsq
我点击了“运行”按钮,但输出的白色矩形仍然是白色的。如果你正在创建一个fiddle,它应该做一些明显的事情。我不认为Fiddle模拟日志、调试器或网络工具。实际上,控制台日志是WebExtensions的另一个区域,对我来说并不起作用。在我的后台和前台代码中,console.log()很少生成任何输出。为什么?它是异步的,需要暂停吗?我怀疑这一点。 - David Spector

-1

有一个技巧,定义一个数组或对象并将其赋值:

    let Result=[];
    let callImport = (load)=>{ 
        import('./component.js').
            then((Module)=>{
                load[0] = Module;
            });};
    callImport(Result);
    setTimeout(()=> console.log(Result[0]),10);

在这里,我使用了setTimeout作为await,以防止在promise执行完成之前打印结果。这是没有使用setTimeout的Codepen示例:https://codepen.io/MNSY22/pen/NWPdvxd


不是这样的..如果在调用callImport()之后没有使用setTimeout,直接console.log(Result),Result仍然会显示旧值。 - Vikram
这是真的,对我有用。这是示例代码,我不想让它太复杂。你需要使用sync await,就像添加async (load)=>{await import('..。 - Mohsen
Async await 是 JavaScript 的语法糖,使异步代码看起来像同步代码。但这并不意味着你的代码自动变成了同步代码。 - Vikram
超时不是处理异步输入的正确方法。如果你的请求时间超过了设定时间,那么它将会失败。 - JESii
1
@JESii 我知道超时不是处理的方法,正如我在评论中解释的那样,我将其作为示例放置以展示这个技巧的工作原理,您可以根据需要实现它。这里有一个 Codepen 示例,可以向您展示它的工作方式,希望能找到您的答案:https://codepen.io/MNSY22/pen/NWPdvxd - Mohsen

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