JavaScript异步或同步请求的返回值

3
下面的函数首先执行同步比较test == 0,如果通过,则返回一些内容;如果未通过,则执行异步请求。我的意图是让后者返回其他内容,例如“来自POST回调的某些东西”,但我知道我做错了。在不将Ajax请求更改为同步的情况下,是否有可能实现这一点?
var value = function (test) {
    if (test == 0) {
        return 'value is zero ';
    } else {
        return $.post('/echo/html/', {
            html: 'false ',
            delay: .5
        }, function (r1) {
            console.log('r1', r1);
            return 'something from post callback';
        })
            .done(function (r2) {
            console.log('r2', r2);
            return 'something from done callback';
        });
    }
}(1);

console.log(value);

https://jsfiddle.net/o5kq8he6/2/


1
请使用回调函数或承诺(Promises)代替返回值。 - Sirko
3个回答

6

既然你已经从ajax调用中返回了一个promise,那么在同步比较中,只需返回一个已解决的promise。 然后,两个代码路径都返回已解决的承诺,调用者可以使用相同的代码来处理结果,无论内部工作方式如何。 这是一种常见的设计模式,适用于有时同步,有时异步的代码。

var myFunc = function (test) {
    if (test == 0) {
        return $.Deferred().resolve('value is zero ');
    } else {
        return $.post('/echo/html/', {
            html: 'false ',
            delay: .5
        }).then(function (r2) {
            console.log('r2', r2);
            // this will be the return value of the promise
            return 'something from ajax finished';
        });
    }
};

myFunc(1).then(function(value) {
    // value is here either way
});

FYI,在您的$.post()中同时使用成功处理程序函数和.done()处理程序是没有意义的。如果您要从函数返回一个promise(这是我的建议),那么您应该只使用promise处理程序,而不是成功回调。
您还需要了解,从ajax调用的成功处理程序返回值没有任何用处。该返回值只会回到ajax基础设施的异步部分,并且永远不会被任何东西使用。

根据https://dev59.com/RGYq5IYBdhLWcg3wwDRA#14220323,我认为有效使用`.done`是一个承诺,对吗?同步比较如何返回一个承诺? - user1032531

3
让所有内容都异步化:
var value = function (test, callback) {
    if (test == 0) {
        callback('value is zero ');
    } else {
        return $.post('/echo/html/', {
            html: 'false ',
            delay: .5
        }, function (r1) {
            console.log('r1', r1);
            callback('something from post callback');
        })
            .done(function (r2) {
            console.log('r2', r2);
            callback('something from done callback');
        });
    }
}(1, function(result) { console.log(result); } );

2
你应该使用回调函数而不是第一个返回值。 - Sirko

2
您可以模拟其他操作的异步调用,然后为所有操作使用回调函数:
var value = function (test, callback) {
    if (test == 0) {
        callback('value is zero ');
    } else {
        return $.post('/echo/html/', {
            html: 'false ',
            delay: .5
        }, function (r1) {
            console.log('r1', r1);
            callback('something from post callback');
        })
            .done(function (r2) {
            console.log('r2', r2);
            callback('something from done callback');
        });
    }
}(1, myCallback);


function myCallback(result) {
   // here will the result be
}

如果有需要,您还可以使用setTimeout使同步调用表现得像异步调用。


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