如何使用异步代码在forEach循环上进行promise/callback

How to make promise/callback on forEach loop with async code

本文关键字:promise callback 循环 异步 何使用 代码 forEach      更新时间:2023-09-26

我想我在寻找承诺,但我不知道如何在我的情况下使用它。
我想console.log('ended')只有当我所有的异步代码完成。
我有一个DZ的回调。api而不是forEach(),最好的方法是什么?

    _.forEach(filteredTracks, function(n) {
        DZ.api('/playlist/'+ n.id +'/tracks', function(response) {
            _.forEach(response.data, function(n) {
                SP.api('/search/'+n.title, function(response) {
                    console.log(response);
                });
            });
        });
    });
    console.log('ended');

你要找的是Promise。all -> Promise.all(arrayOfPromise).then(function (result) {})

对于当前的代码,如果SP.api已经与Promise兼容,只需执行:

_.map(filteredTracks, function(n) {
    return DZ.api('/playlist/'+ n.id +'/tracks')
            .then(function (response) {
                _.map(response.data, function(n) {
                    return SP.api('/search/'+n.title);
                });
                return Promises.all(response.data);
            });
    });
});
Promise.all(filteredTracks)
    .then(function (results) {
        console.log('ended');
    });

如果SP.api和DZ Api没有返回Promise,你可以:

承诺SP.api DZ Api和使用相同的代码我写在

或者在._map

中返回承诺
_.map(filteredTracks, function(n) {
    var promise = new Promise(function (resolve, reject) {
        DZ.api('/playlist/'+ n.id +'/tracks', function (response) {
                _.map(response.data, function(n) {
                    var insidePromise = new Promise(function (resolve, reject) {
                        return SP.api('/search/'+n.title, function (result) {
                            resolve(result);
                        });
                    })
                    return insidePromise;
                });
                resolve(Promises.all(response.data));
            });
        });
    });
    return promise;
});
Promise.all(filteredTracks).then(function (results) {
        console.log('ended');
    });

您想要的是将forEach替换为map,并让每个调用返回一个Promise,连接内部循环的结果,因为您有两个级别。然后将Promise数组传递给Promise.all(),它将创建一个Promise,当数组中的所有Promise都已解析时,该Promise将进行解析。要做到这一点,你必须重构你的代码,从DZ.api函数返回一个Promises,而不是使用回调。简而言之:

let promises = filteredTracks.map(track => {
    return DZ.promisedApi(track).then(response => {
        return Promise.all(response.data.map(n => SP.promisedApi(n))
    }) 
})
Promise.all(promises).then(() => console.log("done!"))

您没有指定您正在使用的库,但总的来说,我可以建议您将所有API调用的承诺保存到一个数组中,然后使用promises .all()

所以你会得到类似(警告:未经测试的代码,仅供参考):
var promisesArray = []
_.forEach(filteredTracks, function(n) {
    DZ.api('/playlist/'+ n.id +'/tracks', function(response) {
        _.forEach(response.data, function(n) {
            promisesArray.push( SP.api('/search/'+n.title, function(response) {
                console.log(response);
            }));
        });
    });
});
Promise.all(promisesArray)
        .then(function(value){
          console.log('ended');
        })

基本上,正如Promise参考页面所述,Promise。all创建一个新的Promise,当所有作为参数传递的Promise都被解析时,该Promise将进行解析。在我看来,这符合您的用例。