节点js异步转换为同步

Node js async convert to sync

我需要同步推送数据到数组。首先API请求获取图片key base 一个需要在循环内获取图片数据的。

 var deasync = require('deasync');


        router.get('/a', function(req, res) {
                var username="user";
                var passw ="pass";
                var op = [];
                var args = {
                    headers: {
                    'Authorization': 'Basic ' + new Buffer(username + ':' + passw).toString('base64')
                }   
            };
         //this is first api request
        client.get(global.apiUrl+"V1/ProductItem", args,
        function (data, response) {
                //this is second api request
            data.forEach(function(img) {client.get(global.apiUrl+"V1/ImagePreview/"+img.AvatarKey,args,
                    function (data2, response){
                               img['data']=data2.Image;
                               deasync(pushData(img));
                          });
                    });     
                });

        function pushData(img){
            op.push(img);//array push 
        }
        res.render('test1', { "out":JSON.stringify(op) });
        });

尽管我认为 deasync 是解决您的特定问题的糟糕选择,但使用它的关键是 "deasync" 异步函数。由于 Array.push 是同步的,取消同步 Array.push 没有任何意义

阅读了 deasync 的文档,使用起来相当简单

var deasync = require('deasync');
// create a sync client.get
function syncClientGet(client, url, args) {
    var inflight = true;
    var ret;
    client.get(url, args, function(data, response) {
        // as your original code ignores response, ignore it here as well
        ret = data;
        inflight = false;
    });
    deasync.loopWhile(() => inflight);
    return ret;
}

router.get('/a', function(req, res) {
    var username = "user";
    var passw = "pass";
    var op = [];
    var args = {
        headers: {
            'Authorization': 'Basic ' + new Buffer(username + ':' + passw).toString('base64')
        }
    };

    let data = syncClientGet(client, global.apiUrl + "V1/ProductItem", args);
    data.forEach(function(img) {
        let data2 = syncClientGet(client, global.apiUrl + "V1/ImagePreview/" + img.AvatarKey, args);
        img['data'] = data2.Image;
        op.push(img);
    });
    res.render('test1', {
        "out": JSON.stringify(op)
    });
});

然而,拥抱异步性,您发布的代码可以很容易地写成

router.get('/a', function (req, res) {
    var username = "user";
    var passw = "pass";
    var op = [];
    var args = {
        headers: {
            'Authorization': 'Basic ' + new Buffer(username + ':' + passw).toString('base64')
        }
    };
    client.get(global.apiUrl + "V1/ProductItem", args, function (data, response) {
        data.forEach(function (img) {
            client.get(global.apiUrl + "V1/ImagePreview/" + img.AvatarKey, args, function (data2, response) {
                img['data'] = data2.Image;
                op.push(img);
                if (img.length == data.length) {
                    res.render('test1', {
                        "out": JSON.stringify(op)
                    });
                }
            });
        });
    });
});

或者,使用 Promises

router.get('/a', function (req, res) {
    var username = "user";
    var passw = "pass";
    var args = {
        headers: {
            'Authorization': 'Basic ' + new Buffer(username + ':' + passw).toString('base64')
        }
    };
    // create a Promisified client get
    var clientGetPromise = function clientGetPromise(client, url, args) {
        return new Promise(function (resolve, reject) {
            return client.get(url, args, function (data, response) {
                return resolve(data);
            });
        });
    };

    clientGetPromise(client, global.apiUrl + "V1/ProductItem", args).then(function (data) {
        return Promise.all(data.map(function (img) {
            return clientGetPromise(client, global.apiUrl + "V1/ImagePreview/" + img.AvatarKey, args).then(function (data2) {
                img['data'] = data2.Image;
                return img;
            });
        }));
    }).then(function (op) { // op is an Array of img because that's how Promise.all rolls
        return res.render('test1', { "out": JSON.stringify(op) });
    });
});