node.js - Gunakan nod sebagai perangkak untuk mensimulasikan antara muka untuk mendapatkan data dalam gelung Bagaimanakah async/menunggu mencapai operasi segerak dan mengawal proses?
给我你的怀抱
给我你的怀抱 2017-07-06 10:36:31
0
4
1653

Idea semasa adalah seperti berikut: 1. Dapatkan semua URL halaman teg di bawah kategori, 2. Gelung melalui halaman rangkak untuk merebut halaman teg semasa untuk mendapatkan alamat json api, 3. Dapatkan senarai produk teg semasa , 4. Dapatkan Produk semasa yang dimuatkan dalam halaman bertab.

Tetapi apa yang dilakukan sekarang ialah pada permulaan langkah kedua, ia tidak menunggu sehingga 2-4 selesai sebelum menggelung ke langkah seterusnya saya cuba menggunakan async/await, tetapi kawalan proses tidak dilaksanakan. Meminta nasihat di sini.

var http = require('http');
var fs = require("fs");
var superagent = require('superagent');
var urls = [];
var pageIndex = 1;
var xlsxData = '';

getGoodsUrl(urls);

function getGoodsUrl(urls){
    superagent
        .post('http://bravetime.davdian.com/index.php?c=Index&a=getCatNavList')
        .type('text/html; charset=utf-8')
        .set('Accept','application/json, text/javascript, */*; q=0.01')
        .end(function(err, res) {
            if (err) {
                console.log('分类数据请求失败');
            } else {
                console.log('分类数据请求成功');
                var resData = res.text;
                var resData = JSON.parse(resData); 
                if(resData.data.length > 0){
                    resData.data.forEach(function(item){
                        var rowObj = [];
                        var title = item.title;
                        var category = item.content.category;
                         category.forEach(function(item){
                             var text = [];
                             text.push(title+ '--' + item.text);
                             text.push(item.link);
                            rowObj.push(text);
                         });
                         urls.push(rowObj);
                     });
                     loopUrls(urls);
                } else {
                    console.log('分类数据为空');
                }

                // saveInfo(xlsxData);
            }
        })
}

function loopUrls(urls){
    urls.forEach(function(item){
        var row = item;
        row.forEach(function(item){
            var tagTitie = item[0];
            var tegUrl = item[1];
            getApiUrl(tagTitie,tegUrl);
        });
    });
}

function getApiUrl(title,url){
    var realUrl = 'http://bravetime.davdian.com' + url;
    http.get(realUrl,function(res){
         var html = '';
         res.on('data',function(data){
             html += data;
         });
         res.on('end',function(){
             console.log('正在获取' + title + '页面数据');
             var reg = /goodsUrl = "(.+)"/;
             var apiUrl = reg.exec(html);
             getGoodsJson(apiUrl[1],pageIndex);
         });
     }).on('error',function(){
         console.log('获取html出错!!');
     });
}

function getGoodsJson(url,pageIndex){
    superagent
        .post('http://bravetime.davdian.com/' + url + 'page_size=10&rp=catergory_search&rl=list')
        .send({page:pageIndex})
        .type('application/x-www-form-urlencoded; charset=UTF-8')
        .set('Accept','application/json, text/javascript, */*; q=0.01')
        .end(function(err, res) {
            if (err) {
                console.log('第' + pageIndex + '页请求失败');
            } else {
                console.log('第' + pageIndex + '页请求成功');
                var resData = res.text;
                var resData = JSON.parse(resData); 
                if(resData.data.length > 0){
                    resData.data.forEach(function(item){
                         xlsxData = xlsxData + item.goods_name + '  ' + item.shop_price + '  ' + item.goods_number + '\r\n';
                     });
                     pageIndex = parseInt(pageIndex) + 1;
                     setTimeout(function(){
                         getGoodsJson(url,pageIndex);
                     },200);
                } else {
                    console.log('数据已加载完毕');
                    saveTxt(xlsxData);
                    pageIndex = 1;
                    return false;
                }

                // saveInfo(xlsxData);
            }
        })

}

function saveTxt(data){
    fs.writeFile("create.txt",data,function (err) {
        if (err) throw err ;
         console.log("File Saved !"); //文件被保存
    }) ;
}
function saveInfo(data){
     var buffer = xlsx.build([{name: "mySheetName", data: data}]);
     fs.writeFileSync("myFile.xlsx", buffer, 'binary');
     console.log('excel保存成功');
}

Berikut ialah gambar rajah hasil dan urutan pelaksanaan kod:

给我你的怀抱
给我你的怀抱

membalas semua(4)
Peter_Zhu

penjana
async
janji

仅有的幸福

Keseluruhan proses anda adalah tidak segerak dan anda tidak melihat sebarang maksud penyegerakan. Saya rasa anda mungkin tidak faham apa itu tak segerak.

Async/wait adalah berdasarkan Promise, dan Superagent sendiri menyokong Promise Anda boleh menggunakan async/wait secara terus.

async function() {
  try {
    const result = await superagent.get(url);
    console.log(result.headers);
    console.log(result.body);
  } catch (error) {
    console.error(error);
  }
}

http://visionmedia.github.io/...

http://www.ruanyifeng.com/blo...

Maka apa yang anda perlukan hanyalah meletakkan http.get() 换成 superagent.get().

習慣沉默

Secara amnya, orang ramai tidak mempunyai kesabaran untuk membaca logik perniagaan orang lain.

Seperti yang dinyatakan di atas, Async/await adalah berdasarkan Promise Jika antara muka API pustaka pihak ketiga yang anda panggil tidak mengembalikan objek janji, jika anda ingin menggunakan Async/menunggu, anda hanya boleh mencipta objek janji baharu di. setiap langkah. Ini sebenarnya sangat menyusahkan untuk menulis. Sudah tentu, ia akan menjadi sangat mudah jika ia boleh mengembalikan objek janji.

Perkara berikut ditulis menggunakan acara modul teras nod tanpa janji, untuk rujukan anda:

const EventEmitter = require('events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();

myEmitter.on('step1', (m) => {
    //第一步
    //业务逻辑处理得到结果result1
        
    //判断是否触发下一步,如有需要将这步的结果传给下一步
    myEmitter.emit('step2', result1);
   
});
myEmitter.on('step2', (result1) => {
    //第二步
    //业务逻辑处理得到结果result2
        
    //判断是否触发下一步,如有需要将这步的结果传给下一步
    myEmitter.emit('step3', result2);
});
myEmitter.on('step3', (result2) => {
    //以此类推
});
myEmitter.emit('step1', urls);
刘奇

Boleh guna Node8 util.promisify , atau Bluebird, dsb. tukar fungsi gaya panggil balik Node kepada fungsi gaya Promise, dan kemudian anda boleh menggunakan async/await untuk menulis kod.

Kod itu sendiri masih merupakan panggilan tak segerak, tetapi kaedah penulisan kelihatan segerak. Oleh itu, anda masih perlu memberi perhatian kepada struktur proses semasa menulis, terutamanya semasa menulis gelung. Kod itu terlalu panjang, jadi saya menulis contoh kecil untuk menggambarkan

async function remoteCall() {
    // do something
}

list = [];  // 假设是很多数据


async function process() {
    // 这种写法必须要一个 remoteCall 完成之后才进行另一个
    for (let i = 0; i < list.length; i++) {
        await remoteCall();
    }

    doAfter();
}

async function process2() {
    // 这种写法没法 await
    list.forEach(function(t) {
        remoteCall();
    });
}

async function process3() {
    // 这种写法 doAfter 一早就会执行
    list.forEach(async function(t) {
        await remoteCall();
    });

    // 它可能会在 remoteCall() 之前
    doAfter();
}

async function process4() {
    // 这种写法必须要全部 remoteCall 成功才能进行到 doAfter
    // remoteCall返回的 promise 如果 reject 会抛异常
    var promises = list.map(t => remoteCall());
    await Promise.all(promises);
    doAfter();
}
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan