js非同期プログラミングをプレイ
10693 ワード
js非同期プログラミング
一般的には、
このハード需要を解決するために、Javascript言語は2つの言語パターンを提案しています.同期(Synchronous)と非同期(Aynchronous).
非同期のいくつかの一般的な方法コールバック関数 購読とリリースモード Promise generator async/await コールバック関数の方法
一つの関数をパラメータとして別の関数に導入することで、一定の条件を満たすと、calback関数が実行されます.
使い方:
購読モードを公開
pub/subモードはjs設計モードの一つで、自身はjavaに鑑みてのモードですが、非同期処理をする時に非常に役立ちます.一つの情報センター
Promise
今の基本的な前端人員については、
Promise.resolive valueは3つの値があります.単一値 の つの
もし一つの要求の結果が次の要求のパラメータであれば、オリジナルの要求方法を使えば、右矢印のような反転地獄が出現します.
何重にもはまっていて、非常に怖いです.メンテナンスには不便です.prmiseを通じて地獄に戻りますか?
複数の要求を同時に処理する場合(サーバの返却順序は不要)
上記の方法は要求の返却結果が保証されていません.あなたが送った順番で戻ってきます.もし完全な応答の結果を私の希望の順序で返したいなら、どうすればいいですか?
generatorコンストラクタ
generatorは、1つのコンストラクタであり、
generator非同期運用
コンストラクタの一時停止と継続の機能を利用して、非同期要求をうまく処理して、データを得てから他の内容を行うことができます.
得られたデータを内部的に処理したいなら?
上記の私の呼び出し方法から分かるように、
ES 7は、同期コードのように非同期的な動作が簡単で便利になるように、
await:後にpromiseの例を受けます.
*async:promiseオブジェクトを返します.*
簡単な非同期要求
複数の要求を同時に処理する場合(サーバの返却順序は不要)
ASync/awaitで複数の要求を同時に処理します.awaitの後に
複数の要求を同時に処理し、データを返す順序を確保する必要がある(運用シーンが少ない)
データの中にお互いの連絡がないと、また一つずつ送りたいです.これでいいです.
図解async/awati
一般的には、
js
足どりの言語の実行環境は単スレッドであることがわかっています.つまり、一つのタスクが完了するまで、二つ目のタスクを行い、そして下にずっと進行します.このような実行環境は簡単ですが、複雑な運用はできません.一つの要求が非常に長い間必要となると、次のプロセスは座礁されます.プロセスはこのようにして崩れました.このハード需要を解決するために、Javascript言語は2つの言語パターンを提案しています.同期(Synchronous)と非同期(Aynchronous).
非同期のいくつかの一般的な方法
一つの関数をパラメータとして別の関数に導入することで、一定の条件を満たすと、calback関数が実行されます.
使い方:
//
function fn1(a, fn) {
if(a > 10 && fn instanceof Function) {
fn.call()
}
}
function fn2() {
console.log(' --- fn2 ----')
}
//
function fn3(fn) {
setTimeout(() => {
console.log('--- fn3 ---')
fn.call()
},1000)
}
//
fn1(12, fn2)
fn3(fn2)
非同期をコールバック関数によって処理することは、非同期の初期の場合であり、jquery
の多くは、コールバックによってコールバックを実現する.しかし、このようなモードコードは比較的結合されており、コードの維持には不利である.購読モードを公開
pub/subモードはjs設計モードの一つで、自身はjavaに鑑みてのモードですが、非同期処理をする時に非常に役立ちます.一つの情報センター
EventCenter
によって処理される傍受(on
)とトリガ(triggle
).前の文章を参考にして、最後のデザインモードを作成します.function fn1() {
setTimeout(() => {
// data
let data = fetch(.....)
// waterFull, data
Event.triggle('waterFull', data)
},2000)
}
fn1()
Event.on('waterFull', (data) => {
//
console.log(data)
})
pub/subモードを通じて、私達は情報センターで信号の出所がはっきり見えます.便利な集中管理は、モジュール化の管理にもっと便利です.しかし、プロジェクト全体でpub/subモードを使うと、流れがよく分かりません.データの入手とデータの処理が分離して、後期のメンテナンスにも大きな問題があります.Promise
今の基本的な前端人員については、
Promise
を聞いたことがないと言っていますが、もしプロミスをたくさん見ていなかったら、阮先生のes 6文書Promiseを確認できます.以下は主に具体的な要求によってpromiseを実現します.詳しく説明しません.Promise
コンストラクタは承諾となり、3つの状態resolve
、reject
、pending
に分けられ、一旦状態がpending
から他の2つの状態に変化したら、修正できなくなり、一つの承諾と同じである.Promise
は、2つのパラメータresolve
を受信し、reject
は、成功後の実行および失敗後の実行をそれぞれ表し、インスタンスthen()
の方法で関数を伝達することができる.// Promise
const promise = new Promise((resolve, reject) => {
// some code
if(success) resolve(value)
else reject(err)
})
promise.then(/* */(data) => { console.log(data) }).catch(/* */(err) => { console.log(err) })
ここで見たら、これは非同期処理と何か関係があると言うかもしれませんか?あなたが考えてみてください.非同期操作の後、いつ終わるかは気にしなくてもいいです.一人で約束したように、私は彼の約束通りにします.この件はもう処理されました.便利ではないですか?let promise = new Promise((resolve, reject) => {
let data = fetch('url') //
resolve(data)
})
promise.then(data => console.log(data));
// fetch promise
fetch('http://ons.me/tools/dropload/json.php?page=0&size=4').then(response => response.json()).then(data => console.log(data)) //
//
私は全然心配しなくてもいいです.その中はどうやって実現されましたか?どうせ約束したら結果をくれます.私はthen()
方法で受け入れるだけでいいです.Promise.resolive valueは3つの値があります.
promsie
の例thenable
オブジェクトPromise.resolve(value).then((value) => {})
一つの要求が他の要求に依存する場合を処理する.もし一つの要求の結果が次の要求のパラメータであれば、オリジナルの要求方法を使えば、右矢印のような反転地獄が出現します.
何重にもはまっていて、非常に怖いです.メンテナンスには不便です.prmiseを通じて地獄に戻りますか?
function send(url) {
return new Promise((resolve, reject => {
ajax(data);
if(' ') resolve(data)
else reject
}))
}
send('url1').then(data => send('url2'))
.then(data => send('url3'))
.then(data => send('url4'))
.then(data => console.log(data)) //
//
Promise.resolve(1).then(val1 => val1+2).then(val2 => val2+3).then(val3 => console.log(val3)) //6
上記のリターン地獄は見ていても便利ですか?コードも簡単です.依存性も強いです.その後もasync/await
を通して簡略化していきます.複数の要求を同時に処理する場合(サーバの返却順序は不要)
Promise.all(arr)
は、1つのpromiseのインスタンスの配列を受け入れ、複数の要求をサーバに同時に提供することができるが、これはサーバの処理速度に依存する、受信された順序を保証することができない.// url , setPromise promise , promsie
let urlArr = [url1, url2, url3]
Promise.all(urlArr.map(url => setPromise(url))).then(data => console.log(data))
// , 。
複数の要求を同時に処理し、データを返す順序を確保する必要がある(運用シーンが少ない)上記の方法は要求の返却結果が保証されていません.あなたが送った順番で戻ってきます.もし完全な応答の結果を私の希望の順序で返したいなら、どうすればいいですか?
let urlArr = [url1, url2, url3];
let totalData = []
// , , Promise.
urlArr.reduce((promise, url) => {
return promise.then(() => setPromise(url)).then(data => { totalData.push(data) })
}, Promise.resolve())
このようにして、各要求が完了するのを待って、得られたデータpush
からtotalData
の中に、私たちが望む値を順番に得ることができる.もちろんasync/await
を使うともっと便利です.後で説明します.generatorコンストラクタ
generatorは、1つのコンストラクタであり、
generator
は、関数の内部部分を実行するのではなく、コンストラクタオブジェクトに戻り、コンストラクタオブジェクトのnext()
を介して関数本体を呼び出し、yield
に会うたびに実行を停止し、オブジェクトに戻る.function* gen() {
console.log(`---- start ---`)
yield 1
yield 2
return 3
}
let g = gen() // generator ,
g.next() // console---- start --- return { value: 1; done: false }
g.next() // {value: 2; done : false}
g.next() // {value: 3; done: true}
g.next() // {value: undefined; done: true}
yield
自体は、コンテンツを後悔することはないので、ビルダオブジェクトにコンテンツを返しただけで、yield
表現もコンテンツに戻りたいなら、次のnext()
にパラメータを伝えることができます.function* gen() {
let a = yield 1
console.log(a)
yield 2
return 3
}
let g = gen();
// yield 1
g.next() // {value: 1, done: false}
// , yield 1 ggg
g.next('ggg') // console ggg {value: 2, done: false}
next()
を通してパラメータを伝達することで、値を内部に伝達することができ、後の非同期処理に役立つ.generator非同期運用
コンストラクタの一時停止と継続の機能を利用して、非同期要求をうまく処理して、データを得てから他の内容を行うことができます.
yield
式を用いてpromise
オブジェクトを返す原理です.function* send() {
let data = yield fetch('https://suggest.taobao.com/sug?code=utf-8&q=%E6%89%8B%E6%9C%BA');
}
let objData;
//
send().next().value.then( response => response.json()).then(data => objData = data)
このようにインタフェースで要求されたデータを入手しました.これまでのプロミス関数の書き込みよりもずっと簡単です.同期と同じ操作です.得られたデータを内部的に処理したいなら?
// , yield
function* send() {
let data = yield fetch('https://suggest.taobao.com/sug?code=utf-8&q=%E6%89%8B%E6%9C%BA');
data.result.map(item => {
return item.push(11)
})
return data
}
let objData;
let gen = send()
// promise 。
gen.next().value.then( response => response.json()).then(data => gen.next(data)).then(data => objData=data)
//
var gen = function* (){
var f1 = yield readFile('/etc/fstab');
var f2 = yield readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
//
const g = gen()
g.next().value.then(data => {
//
g.next(data).value.then(data => {
//
g.next(data);
})
})
簡単なcoモジュール処理generator複数の関数要求上記の私の呼び出し方法から分かるように、
Promise + generator
の非同期処理を利用して、データをthen()
の方法で処理し続けている.一つの方法がありますか?私は直接に関数を実行してほしい値を得ることができます.たとえば:function* send() {
let data = yield fetch('https://suggest.taobao.com/sug?code=utf-8&q=%E6%89%8B%E6%9C%BA');
return data
}
run(send) // data
// TODO
function run(gen) {
const g = gen();
function next(data) {
let result = g.next(data);
// , value
if(result.done) return result.value
result.value.then(data => {
//
next(data)
})
}
next()
}
オンラインでは、多くの方法がカプセル化されています.例えば、一般的なrun
ライブラリでは、このような処理方法がco関数です.しかし、私たちが複数の要求を送る時、あなたはこのように書くかもしれません.function* send() {
var p1 =yield request( "http://some.url.1" );
var p2 =yield request( "http://some.url.2" );
var r3 = yield request(
"http://some.url.3/?v=" + r1 + "," + r2
);
console.log(r3)
}
// run
run(send)
このように書くと要求が送信されますが、複数の要求を同時にするのではなく、最初の要求p 1を待ってから、第二の要求p 2を行います.性能最適化の面では不利です.また、私たちの要求に合わないです.どうやって2つの要求が独立しますか?また、2つの要求の結果を得ることによって、他の要求を行うことができます.私たちはこのようにすることができます.function* send() {
//
var p1 = request( "http://some.url.1" );
var p2 = request( "http://some.url.2" );
// , yield
const d1 = yield p1;
const d2 = yield p2;
var r3 = yield request(
"http://some.url.3/?v=" + d1 + "," + d2
);
}
このように書くのは前に書いたPromise.all()
と似ていますか?このように変更できます.function* send() {
// ,
const [d1, d2] = yield Promise.all([
request( "http://some.url.1" ),
request( "http://some.url.2" )
])
var r3 = yield request(
"http://some.url.3/?v=" + d1 + "," + d2
);
}
async/await非同期処理ES 7は、同期コードのように非同期的な動作が簡単で便利になるように、
async/await
の内部にasync/await
をカプセル化した処理があるため、全generator
を用いて非同期的な処理をする人は少ないが、非同期の推進においてgenerator
が大きな役割を果たしている.await:後にpromiseの例を受けます.
*async:promiseオブジェクトを返します.*
簡単な非同期要求
async function f() {
// , 。
let data = await fetch('').then(res => res.json())
console.log(data) //
return data // promise
}
async function h() {
let data = await Promise.resolve(22);
console.log(data); // 22
return data // Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 22}
}
async function c() {
try {
let data = await Promise.reject(22);
console.log(11) //
} catch(e){
console.log(222) // 222
}
return 333 // Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 333}
}
上の例はgeneratorの中の非同期要求と似ていますか?同期のようにコードを作成することができますが、generatorよりもawaitの後にpromiseを追加して直接に該当データを返します.複数の要求を同時に処理する場合(サーバの返却順序は不要)
ASync/awaitで複数の要求を同時に処理します.awaitの後に
generator
例を追加する必要があるので、頭の中で一気にPromise
例を思いつきましたか?// request promise
async function send() {
// ,
const [d1, d2] = await Promise.all([
request( "http://some.url.1" ),
request( "http://some.url.2" )
])
}
気になるかもしれませんが、どうしてPromise.all()
のように追加の関数で呼び出す必要がないですか?複数の要求を同時に処理し、データを返す順序を確保する必要がある(運用シーンが少ない)
データの中にお互いの連絡がないと、また一つずつ送りたいです.これでいいです.
let patharr = [url1, url2, url3]
async function main2() {
let arrData = [];
// for
for(const url of pathArr) {
arrData.push(await request(url));
}
return arrData
}
異歩の好文図解async/awati