(4)の合計JS - 非同期

1.非同期

この記事は、分割されたJSNode4つの章の前に、二部JSとしての後、Nodeそれが書かれていませんので、それは少しのクロスに見える、同時に、。

1.1コンセプト

非同期タスクは、すぐに結果を得ることはありませ呼び出すことですタスクの予想される結果に追加の操作を必要とし、メインスレッドを入力せずに非同期タスクは、「タスクキュー」に、唯一の「タスクキューは、」メインスレッドに通知し、非同期タスクは、実行することができますタスクは、実行のメインスレッドを入力します

1.2問題

コールバック関数呼び出しの順序は保証されませんので、そのための非同期呼び出しのため、返されたデータの時間を決定することはできません。
関数の実行順序を保証するために、ネストされた非同期非同期メソッドがあったとしても知られている非常に醜いネストされたコードを生成する:コールバック地獄

1.3ソリューション

JSネイティブ非同期申し出多くのソリューション、中JSまたはNode使用中に直接に。
その他の人気の主Promiseasync2種類。

2.約束

2.1意味と使用

非同期プログラミングは、従来のソリューションに比べ、より合理的であると強力なソリューションである
プロミスオブジェクトが2つの特性があります。

  1. それは3つの状態がありPendingFulfilledRejected外部からの影響から自由州、非同期操作の結果によってのみ影響を受けます
  2. 2つのだけの可能な状態の変化Pending → FulfilledPending → Rejected限り状態変化が再び変更して、そこに滞在しませんよう

短所:

  1. 新しく直ちに実施し、キャンセルすることはできませんし、外部の内部エラーに反応しないであろうしたら
  2. Pending状態、我々は非同期動作条件の進捗状況を知ることができません
// 图片异步加载
function loadImageAsync (url) {
    return new Promise((resolve, reject) => {
        const image = new Image()
        
        image.onload = function () {
            resolve({
				image: image,
				newUrl: './photo.png'
			})
        }
        
        image.onerror = function () {
            reject('Load Error!')
        }
        
        image.src = url
    })
}

// Promise状态传递
const p1 = new Promise((resolve, reject) => {
    setTimeout(() => reject('Fail'), 3000)
})

const p2 = new Promise((resolve, reject) => {
    setTimeout(() => resolve(p1), 1000) // 由于resolve了p1是另一个Promise,因此p2状态由p1决定
})

p2.then(res => console.log(res, 'then'))
    .catch(err => console.log(err, 'catch')) // Fail catch

2.2方法

2.2.1 Promise.prototype.then()

then状態変化、及び戻り新規追加するためのコールバック関数Promiseインスタンスは、チェーンを呼び出すことができます。then戻り値は新たにパッケージされるPromiseインスタンスと戻り、最初のパラメータはResolved、コールバック、第二Rejectedのコールバック。

loadImageAsync('./image.png').then(res => {
    return loadImageAsync(res.newUrl)
}).then(() => {console.log('success')}, () => {console.log('fail')})
2.2.2 Promise.prototype.catch()

Promise.prototype.then(null, rejection)エイリアスはそれが新しい返し、エラーが発生したときにコールバック関数を指定するために使用されPromise、コールが背後に連鎖させることができますインスタンスをcatch目の前にキャッチしますcatch投げ間違っています。これはお勧めcatch使用するのではなく、then(null, rejection)

// resolve改变了状态,抛错不会被捕获,没有任何反应
new Promise((resolve, reject) => {
    resolve('success')
    throw new Error('error')
}).catch(err => {
    console.log(err)
})
// 会冒泡到最外层
new Promise((resolve, reject) => {
    resolve('success')
    setTimeout(() => throw new Error('error'), 0) 
}).catch(err => {
    console.log(err)
})
// Promise的fail被捕获,new error不会被捕获,也不会冒泡到外层
new Promise((resolve, reject) => {
    reject('fail') // reject方法等同于 throw new Error()
}).catch(err => {
    console.log(err) // fail
    throw new Error('new error')
}).then(res => console.log(res))
2.2.3 Promise.all()

複数のPromise新たにパッケージインスタンスPromiseインスタンスは、パラメータが有するIteratorインタフェースを、それぞれのデータであるPromiseインスタンス。
状態は状況を変えます:

  1. 状態のすべてのメンバーはなってきたFulfilled、それは国家の新しいインスタンスになり、Fulfilledコールバック関数に渡された戻り値からなる配列のすべてのメンバー。
  2. 任意の状態のメンバーになるRejected、状態は、新しいインスタンスになるRejectedと最初Rejectedのコールバック関数に渡される戻り値のインスタンスを

注:自己状態は、プロセスブロックされるコールバックのいずれかのデータメンバーが行動に関与したコールバックの新しいインスタンスを渡します

// p1处理catch
const p1 = new Promise((resolve, reject) => reject('error'))
    .catch(err => console.log(err)) // error
const p2 = new Promise((resolve, reject) => resolve('success'))
const p3 = new Promise((resolve, reject) => resolve('success'))

Promise.all([p1, p2, p3]).then(res => console.log(res))
    .catch(err => console.log(err)) // [undefined, 'success', 'success']
    
// p1处理catch, p3处理then
const p1 = new Promise((resolve, reject) => reject('error'))
    .catch(err => console.log(err)) // error
const p2 = new Promise((resolve, reject) => resolve('success'))
const p3 = new Promise((resolve, reject) => resolve('success'))
    .then(res => console.log(res)) // success

Promise.all([p1, p2, p3]).then(res => console.log(res))
    .catch(err => console.log(err)) // [undefined, 'success', undefined]
2.2.4 Promise.race()

複数のPromise新たにパッケージインスタンスPromiseインスタンス、質量参加Promise.all同じ。
状態変化の状況:戻り値を持つ最初の状態の新しいインスタンスのメンバーのステータスを変更することを決定。

2.2.5 Promise.resolve()

引数なっプロミスオブジェクトの状態 Resolved

パラメータ 行動
約束の例 変更することなく、そのままの例を返します
オブジェクトは、メソッドを持っています ターニング約束はオブジェクトを返し、その後、すぐにメソッドを呼び出した後、
その他のパラメータ 解決済み戻る約束は状態を持つオブジェクトは、パラメータは、コールバックに渡されます
引数はありません 解決済み戻る約束の状態オブジェクトが持っています
2.2.6 Promise.reject()

引数は、プロミスオブジェクトの状態を回しましたRejectedどのようなパラメータを渡すと、引数のフォローアップの方法は、常にオリジナルの質量の参加です。

const Obj = {
    then () {
        reject('error')
    }
}
Promise.reject(Obj).catch(e => console.log(e === Obj)) // true
2.2.7()、最後に()で行わ独自のパッケージ

行って():チェーンのコールバックエンド、そのスローに見える可能性のあるエラーを確実にするために

// 书上说如下代码只要报错便会向全局抛错,然而then方法的onRejected会自行处理报错,并不会再运行之后的catch
Promise.prototype.done = function (onFulfilled, onRejected) {
    this.then(onFulfilled, onRejected)
        .catch(err => {
                setTimeout(() => { throw err }, 0)
            }
        )
}

new Promise((resolve, reject) => {
    resolve('success')
}).then(res => {
    console.log(res) // success
    res.splice()
}).done(res => {
    console.log(res)
}, err => {
    console.log(err) // 报错
})

// 因此建议不传参,只用作抛错处理,代码改为
Promise.prototype.done = function (onFulfilled, onRejected) {
    this.catch(err => {
    	setTimeout(() => { throw err }, 0)
 	})
}

最終的には():チェーンのコールバックエンド、実装状態の機能を変更するために行われるどんなに

Promise.prototype.finally = function (callback) {
    return this.then(
        value => Promise.resolve(callback()).then(() => value), 
        error => Promise.resolve(callback()).then(() => { throw error }), 
}
2.2.8 Promise.try()

これは、同期機能を使用して非同期処理のために、言及することによる方法であります

// async await已写入规范
const f = () => console.log(1);
(async () => f())()
console.log(2)

// new Promise()
const f = () => console.log(1);
(
    () => new Promise(
        resolve => resolve(f()) // 利用Promise的创建立即执行
    )
)()
console.log(2)

3.非同期

generatorシンタックスシュガー機能、う*置き換えられasync、ますyield交換することがawaitできます。
改善されたポイント:

  1. 呼び出すために、より便利に、内蔵されたアクチュエータ、同様にすることなく、generator同じ呼び出しnext方法
  2. ベター・セマンティクス
  3. より広範な適用性
  4. もっと便利な操作、返すPromiseオブジェクトを

3.1使用

async function test () {
	const file = await getData(url)
	return file
}
test().then(res => {console.log(res)}) // file

async関数は戻りPromise、戻り値はなりターゲットをthen基準方法
awaitの後半に続くコマンドPromiseオブジェクトを、使用されない場合、Promise.resolve生成します

3.2 注意点

  1. 以来async、機能await、それは使用するのが最善であるように、エラーコードは、その後の動作を引き起こすことができないtry ... catch...パッケージをawait使用した後、
  2. 複数のawait同期関係が存在しない場合、それは彼らが同時にトリガーできるように最善のコマンドをあります
  3. await非で使用されるasync誤差関数となり、forEach同時にあなたは間違った結果を得ることができ、機能します

4.非同期I / O

非同期I / Oを使用する理由4.1

  • ユーザーエクスペリエンスを強化
  • 資源のより良い配分

4.2 I / Oおよび非同期I / Oをノンブロッキング

I / Oをブロック:通話が終了するまで、すべてのオペレーティングシステムのカーネルコールの完了後まで待たなければなりませんした後。
I / Oをノンブロッキング:CPUは他のものに対処するために使用することができた後の状態はすぐに、コール後に呼び出しを返します。

4.2.1アンケート
  • 読み:I / Oの状態を確認するための最も原始的な、最低のパフォーマンス、繰り返し電話を
  • 選択:洗練を読んで、時間はファイルディスクリプタの状態によって決定され、同時にファイルディスクリプタ1024をチェックすることができます
  • 世論調査:選択洗練、回避の制限配列の鎖長は、より多くのファイル記述子を確認することができます
  • epoll:Linuxの最も効率的なI / Oメカニズムの下で、I / Oのリターンが目覚めた後、もはや、ポーリング睡眠を入力した後、クエリをトラバース

ポーリング会うI / O要件を非ブロックが、CPUによるファイルディスクリプタや睡眠を横断するために使用されるが、それはまだ良い十分ではありません。

4.2.2マルチスレッドシミュレーション

、スレッドを処理するデータ演算ので、スレッドを計算するために送信I / Oデータとの間の通信を介して、スレッドは、スレッドを取得し、I / Oをブロックするねじ部または非ブロッキングI / O +ポーリング技術はデータへのアクセスを達成するために聞かせて非同期I / Oのこの実現

5.ノードの非同期

5.1イベントループ

ノードの実行モデルは、処理されるべきイベントがあるかどうかを確認していきます。その後、イベントや取り出して次のサイクルを入力し、コールバックを実行するがあります。以下のように実行すべきイベント、終了プロセスはありません。

5.2ビューア

イベントループがあり生产者/消费者模型、非同期I / O、ネットワーク要求や他の生産イベント、イベントは適切なビューアに渡され、視聴者はイベントとイベント処理によって循環から除去しました。

5.3リクエストオブジェクト

Javascriptがオブジェクトの後に、非同期呼び出しを開始する必要があります、オブジェクトが渡されたパラメータと現在のメソッドが含まれ、完成したパッケージ後の状態とコールバック関数は、スレッドプールが要求されたオブジェクトIを実行するために利用可能なスレッドであるとき、スレッドプールに押し込まれたオブジェクト/ O操作とは、結果オブジェクトを格納します。

5.4コールバック

I / O動作が終了したときの結果が要求オブジェクトに格納され、その後、I / O視聴者に通知され、イベントループは、要求されたオブジェクトが対象とコールバック関数と実行のI / O操作の結果から取り出す抽出します。

5.5非I / O、非同期

  1. タイマー
  2. process.nextTick() - アイドル観察者は、マイクロイベントとして理解しました
  3. setImmediate() - チェックオブザーバは、マクロイベントとして理解しました

優先順位の比較:
IDLEオブザーバー> I / Oオブザーバ>チェックオブザーバー

リリース6元記事 ウォンの賞賛0 ビュー81

おすすめ

転載: blog.csdn.net/weixin_44844528/article/details/104408867