JavaScript非同期プログラミングのいくつかの方法

5300 ワード

原文の住所はブラウザーのイベントの巡回の構造(およびnodejsの中のイベントのポーリングの構造)に基づいて、JavaScriptはいつも非同期の環境の中で運行します.JavaScriptは単スレッド言語であり、jsに対する非同期動作は避けられない.解決方法には以下の点があります.
1,コールバック
チューニングはオリジナルの方法でステップ:
// fs => node     
const fs = require('fs');
const readFileAsArray = function(file,cb){
    fs.readFile(file,(err,data)=>{
        if(err) return cb(err);
        // 
=> const lines = data.toString().trim().split('
'); cb(null,lines); }) } readFileAsArray('./numbers.txt',(err,lines)=>{ if(err) throw err; const numbers = lines.map(Number); console.log(` ${numbers} `) }) // 1,2,3,4,5,6,7,9,10,11,12,13
上記の例は、readFileArray()関数の結果によって、readFileArray()関数をフィードバックする.この例は十分に説明しています.コードロジックが複雑か、操作手順が多いと、何階も書いています.読みにくくて、メンテナンスも難しいです.
2,Promise
上記のように、彼の実行順序はコードの手にコントロールされています.(実行順序を手動で調整することができません.できることは一つもありません.表示化の流れは一つもありません.)、promiseはコントロールを戻した人の手に、プロセスがもっと綺麗で、可視化されます.
const fs = require('fs');
const readFileAsArray = function(file){
    return new Promise((resolve,reject)=>{
        fs.readFile(file,(err,data)=>{
            if(err){
                reject(err);
            }
            const lines = data.toString().split('
'); resolve(lines); }) }) } readFileAsArray('./numbers.txt').then( lines=>{ const numbers = lines.map(Number); console.log(`${numbers}`) } ).catch(error=>{ console.log(error) })
しかし、Promiseには、単値/望ましくないなどの欠点があります.
3,await/async
await/asyncはES 7から発売されたシンタックス飴で、PromiseとGeneratorの組み合わせの使い方が内部に封入されています.(プログラマが怠けています.PromiseAPIが多すぎます.await/asyncが現れます.)
const fs = require('fs');
const readFileAsArray = function(file){
    return new Promise((resolve,reject)=>{
        fs.readFile(file,(err,data)=>{
            if(err){
                reject(err);
            }
            const lines = data.toString().split('
'); resolve(lines); }) }) } async function result(){ try{ const lines = await readFileAsArray('./numbers.txt'); const numbers = lines.map(Number); console.log(`${numbers}`) } catch (err){ console.log("await !"); console.log(err); } } result();
4,イベント
プロミスとawait/asyncの関係は計画経済と市場経済のようで、一人はコントロールするために、一つは需要と供給によってコントロールします.
//  ``EventEmitter``         ,                 ,           。
// eventEmitter.on =>        
// eventEmitter.emit() =>       
const EventEmitter = require('events');
const fs = require('fs');
class MyEventEmitter extends EventEmitter {
    executeAsy(asyncFunc,args){
        this.emit('begin');
        console.time('    ');
        asyncFunc(args,(err,data)=>{
            if(err) return this.emit('err',err);
            this.emit('data',data);
            console.timeEnd('    ');
            this.emit('  ')
        })
    }
}
const myEventEmitter = new MyEventEmitter();
myEventEmitter.on('  ',()=>{
    console.log('     ');
})
myEventEmitter.on('data',data=>{
    console.log(`${data}`)
})
myEventEmitter.on('  ',()=>{
    console.log('     ')
})
myEventEmitter.on('err',err=>{
    console.log(err)
})
myEventEmitter.executeAsy(fs.readFile,'./numbers.txt')
イベント=>コード量が多すぎます.
5,rxjs
rxjsと非同期の関係:データをストリームに変換することができます.データの同期によって得られたものでも非同期によって得られたものでも、単一の値ですか?それとも多値ですか?Rx.Observable.ofは単一値同期データを包装するために用いられ、Rx.Observable.froomPromiseは単一値非同期データRx.Observable.froomEventを包装して多値非同期データを包装するために用いられる.
// import { Observable } from 'rxjs'
const fs = require('fs');
const Rx = require('rxjs');
const Observable = require('rxjs')
const EventEmitter = require('events');
class MyEventEmitter extends EventEmitter{
    async executeAsy(asyncFunc,args){
        this.emit("  ");
        try{
            console.time('    ');
            const data = await asyncFunc(args);
            this.emit('data',data);
            console.timeEnd('    ');
            this.emit('  ');
        } catch(err){
            console.log('   !')
            this.emit('error',err)
        }
    }
}
const readFileAsArray = function(file){
    return new Promise((resolve,reject)=>{
        fs.readFile(file,(err,data)=>{
            if(err){
                reject(err);
            }
            const lines = data.toString().split('\r
'); resolve(lines); }) }) } const myEventEmitter = new MyEventEmitter(); myEventEmitter.executeAsy(readFileAsArray,'./numbers.txt'); let dataObservable = Observable.fromEvent(myEventEmitter,'data'); let subscription = dataObservable.subscribe(data=>{ console.log(`${data}`) },err=>{ console.error(err); },compelete=>{ console.info('compelete!'); })
rxjsには、生産者Observeや消費者Observable、プッシュプルモデル、便利なオペレータや関数プログラミングなど、多くの重要な概念があります.ES 8はすでにObservableとObserveの実現に着手しました.nodeも非同期ライフサイクルのフックAync Hookに着手して、プログラマが非同期プログラムを調整しやすくなります.未来のjs非同期プログラムはますます容易になり、機能もますます強くなります.