1.非同期
この記事は、分割されたJS
とNode
4つの章の前に、二部JS
としての後、Node
それが書かれていませんので、それは少しのクロスに見える、同時に、。
1.1コンセプト
非同期タスクは、すぐに結果を得ることはありませ呼び出すことですタスクの予想される結果に追加の操作を必要とし、メインスレッドを入力せずに非同期タスクは、「タスクキュー」に、唯一の「タスクキューは、」メインスレッドに通知し、非同期タスクは、実行することができますタスクは、実行のメインスレッドを入力します
1.2問題
コールバック関数呼び出しの順序は保証されませんので、そのための非同期呼び出しのため、返されたデータの時間を決定することはできません。
関数の実行順序を保証するために、ネストされた非同期非同期メソッドがあったとしても知られている非常に醜いネストされたコードを生成する:コールバック地獄
1.3ソリューション
JS
ネイティブ非同期申し出多くのソリューション、中JS
またはNode
使用中に直接に。
その他の人気の主Promise
とasync
2種類。
2.約束
2.1意味と使用
非同期プログラミングは、従来のソリューションに比べ、より合理的であると強力なソリューションである
プロミスオブジェクトが2つの特性があります。
- それは3つの状態があり
Pending
、Fulfilled
、Rejected
。外部からの影響から自由州、非同期操作の結果によってのみ影響を受けます - 2つのだけの可能な状態の変化
Pending → Fulfilled
やPending → Rejected
。限り状態変化が再び変更して、そこに滞在しませんよう
短所:
- 新しく直ちに実施し、キャンセルすることはできませんし、外部の内部エラーに反応しないであろうしたら
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
インスタンス。
状態は状況を変えます:
- 状態のすべてのメンバーはなってきた
Fulfilled
、それは国家の新しいインスタンスになり、Fulfilled
コールバック関数に渡された戻り値からなる配列のすべてのメンバー。 - 任意の状態のメンバーになる
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
できます。
改善されたポイント:
- 呼び出すために、より便利に、内蔵されたアクチュエータ、同様にすることなく、
generator
同じ呼び出しnext
方法 - ベター・セマンティクス
- より広範な適用性
- もっと便利な操作、返す
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 注意点
- 以来
async
、機能await
、それは使用するのが最善であるように、エラーコードは、その後の動作を引き起こすことができないtry ... catch...
パッケージをawait
使用した後、 - 複数の
await
同期関係が存在しない場合、それは彼らが同時にトリガーできるように最善のコマンドをあります 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、非同期
- タイマー
- process.nextTick() - アイドル観察者は、マイクロイベントとして理解しました
- setImmediate() - チェックオブザーバは、マクロイベントとして理解しました
優先順位の比較:
IDLEオブザーバー> I / Oオブザーバ>チェックオブザーバー