用功率信号来支配异步流程,web播放控件
分类:前端技术

用确定性信号来支配异步流程

2017/08/08 · JavaScript · 异步

原版的书文出处: 十年踪迹   

  • 总结

大家通晓,JavaScript 不管是操作 DOM,还是进行服务端职责,不可幸免必要管理比超多异步调用。在最早,超级多开拓者仅仅通过 JavaScript 的回调格局来拍卖异步,然而这样比较轻松形成异步回调的嵌套,产生“Callback Hell”。

pc28.am神测网 1

新生,一些开采者使用了 Promise 观念来防止异步回调的嵌套,社区将基于观念提议 Promise/A 标准,最终,在 ES6 中放置落成了 Promise 类,随后又遵照 Promise 类在 ES2017 里完结了 async/await,酿成了现行反革命那些简短的异步管理格局。

比如 thinkJS 上面这段代码便是独立的 async/await 用法,它看起来和一同的写法完全相像,只是扩充了 async/await 关键字。

module.exports = class extends think.Controller { async indexAction(){ let model = this.model('user'); try{ await model.startTrans(); let userId = await model.add({name: 'xxx'}); let insertId = await this.model('user_group').add({user_id: userId, group_id: 1000}); await model.commit(); }catch(e){ await model.rollback(); } } }

1
2
3
4
5
6
7
8
9
10
11
12
13
module.exports = class extends think.Controller {
  async indexAction(){
    let model = this.model('user');
    try{
      await model.startTrans();
      let userId = await model.add({name: 'xxx'});
      let insertId = await this.model('user_group').add({user_id: userId, group_id: 1000});
      await model.commit();
    }catch(e){
      await model.rollback();
    }
  }
}

async/await 能够算是后生可畏种语法糖,它将

promise.then(res => { do sth. }).catch(err => { some error })

1
2
3
4
5
promise.then(res => {
    do sth.
}).catch(err => {
    some error
})

转变到了

try{ res = await promise do sth }catch(err){ some error }

1
2
3
4
5
6
try{
    res = await promise
    do sth
}catch(err){
    some error
}

有了 async,await,能够写出原本很难写出的特别轻松直观的代码:

JS Bin on jsbin.com

function idle(time){ return new Promise(resolve=>setTimeout(resolve, time)) } (async function(){ //noprotect do { traffic.className = 'stop' await idle(1000) traffic.className = 'pass' await idle(1500) traffic.className = 'wait' await idle(500) }while(1) })()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function idle(time){
  return new Promise(resolve=>setTimeout(resolve, time))
}
 
(async function(){
  //noprotect
  do {
    traffic.className = 'stop'
    await idle(1000)
    traffic.className = 'pass'
    await idle(1500)
    traffic.className = 'wait'
    await idle(500)
  }while(1)
})()

地点的代码中,我们使用异步的 setTimeout 完毕了一个 idle 的异步方法,重临promise。大多异步管理进度都能让它们再次来到promise,从而发出更简便直观的代码。

网页中的 JavaScript 还恐怕有一个主题素材,正是大家要响应广大异步事件,表示客户操作的异步事件其实不太好改写成 promise,事件代表调控,它和数据与流程往往是四个范畴的业务,所以广大现代框架和库通过绑定机制把这一块封装起来,让开拓者能够集中于操作数据和意况,进而幸免扩充系统的复杂度。

譬如上边十三分“交通灯”,那样写已是超级粗略,然则要是大家要增添多少个“开关”,表示“暂停/继续“和”开启/关闭”,要如何做啊?假诺大家还想要扩张开关,人工控制和切换灯的转换,又该怎么落到实处呢?

有同学想到这里,只怕以为,哎哎那太费力了,用 async/await 搞不定,还是用事情发生以前守旧的不二法门去落到实处啊。

实际上即利用“守旧”的思绪,要落到实处如此的异步状态调节也依旧挺麻烦的,但是大家的 PM 其实也一再会有这么麻烦的须要。

咱俩试着来促成一下:

JS Bin on jsbin.com

function defer(){ let deferred = {}; deferred.promise = new Promise((resolve, reject) => { deferred.resolve = resolve deferred.reject = reject }) return deferred } class Idle { wait(time){ this.deferred = new defer() this.timer = setTimeout(()=>{ this.deferred.resolve({canceled: false}) }, time) return this.deferred.promise } cancel(){ clearTimeout(this.timer) this.deferred.resolve({canceled: true}) } } const idleCtrl = new Idle() async function turnOnTraffic(){ let state; //noprotect do { traffic.className = 'stop' state = await idleCtrl.wait(1000) if(state.canceled) break traffic.className = 'pass' state = await idleCtrl.wait(1500) if(state.canceled) break traffic.className = 'wait' state = await idleCtrl.wait(500) if(state.canceled) break }while(1) traffic.className = '' } turnOnTraffic() onoffButton.onclick = function(){ if(traffic.className === ''){ turnOnTraffic() onoffButton.innerHTML = '关闭' } else { onoffButton.innerHTML = '开启' idleCtrl.cancel() } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
function defer(){
  let deferred = {};
  deferred.promise = new Promise((resolve, reject) => {
    deferred.resolve = resolve
    deferred.reject = reject
  })
  return deferred
}
 
class Idle {
  wait(time){
    this.deferred = new defer()
    this.timer = setTimeout(()=>{
      this.deferred.resolve({canceled: false})
    }, time)
 
    return this.deferred.promise
  }
  cancel(){
    clearTimeout(this.timer)
    this.deferred.resolve({canceled: true})
  }
}
 
const idleCtrl = new Idle()
 
async function turnOnTraffic(){
  let state;
  //noprotect
  do {
    traffic.className = 'stop'
    state = await idleCtrl.wait(1000)
    if(state.canceled) break
    traffic.className = 'pass'
    state = await idleCtrl.wait(1500)
    if(state.canceled) break
    traffic.className = 'wait'
    state = await idleCtrl.wait(500)
    if(state.canceled) break
  }while(1)
  traffic.className = ''
}
 
turnOnTraffic()
 
onoffButton.onclick = function(){
  if(traffic.className === ''){
    turnOnTraffic()
    onoffButton.innerHTML = '关闭'
  } else {
    onoffButton.innerHTML = '开启'
    idleCtrl.cancel()
  }
}

上面这么做完成了决定交通灯的开启关闭。不过事实上那样的代码让 onoffButton、 idelCtrl 和 traffic 各样耦合,有一点惨不忍闻……

那还只是最简便的“开启/关闭”,“暂停/继续”要比那些更复杂,还会有客户自个儿决定灯的切换呢,动脑筋都头大!

在这里种状态下,因为大家把调整和景况混合在同步,所以程序逻辑不可幸免地复杂了。这种复杂度与 callback 和 async/await 无关。async/await 只可以改进度序的布局,并不能够改进内在逻辑的复杂。

那便是说我们该如何是好吧?这里大家将要换风流倜傥种思路,让实信号(Signal)进场了!看上面的事例:

JS Bin on jsbin.com

class Idle extends Signal { async wait(time){ this.state = 'wait' const timer = setTimeout(() => { this.state = 'timeout' }, time) await this.while('wait') clearTimeout(timer) } cancel(){ this.state = 'cancel' } } class TrafficSignal extends Signal { constructor(id){ super('off') this.container = document.getElementById(id) this.idle = new Idle() } get lightStat(){ return this.state } async pushStat(val, dur = 0){ this.container.className = val this.state = val await this.idle.wait(dur) } get canceled(){ return this.idle.state === 'cancel' } cancel(){ this.pushStat('off') this.idle.cancel() } } const trafficSignal = new TrafficSignal('traffic') async function turnOnTraffic(){ //noprotect do { await trafficSignal.pushStat('stop', 1000) if(trafficSignal.canceled) break await trafficSignal.pushStat('pass', 1500) if(trafficSignal.canceled) break await trafficSignal.pushStat('wait', 500) if(trafficSignal.canceled) break }while(1) trafficSignal.lightStat = 'off' } turnOnTraffic() onoffButton.onclick = function(){ if(trafficSignal.lightStat === 'off'){ turnOnTraffic() onoffButton.innerHTML = '关闭' } else { onoffButton.innerHTML = '开启' trafficSignal.cancel() } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
class Idle extends Signal {
  async wait(time){
    this.state = 'wait'
    const timer = setTimeout(() => {
      this.state = 'timeout'
    }, time)
    await this.while('wait')
    clearTimeout(timer)
  }
  cancel(){
    this.state = 'cancel'
  }
}
 
class TrafficSignal extends Signal {
  constructor(id){
    super('off')
    this.container = document.getElementById(id)
    this.idle = new Idle()
  }
  get lightStat(){
    return this.state
  }
  async pushStat(val, dur = 0){
    this.container.className = val
    this.state = val
    await this.idle.wait(dur)
  }
  get canceled(){
    return this.idle.state === 'cancel'
  }
  cancel(){
    this.pushStat('off')
    this.idle.cancel()
  }
}
 
const trafficSignal = new TrafficSignal('traffic')
 
async function turnOnTraffic(){
  //noprotect
  do {
    await trafficSignal.pushStat('stop', 1000)
    if(trafficSignal.canceled) break
    await trafficSignal.pushStat('pass', 1500)
    if(trafficSignal.canceled) break
    await trafficSignal.pushStat('wait', 500)
    if(trafficSignal.canceled) break
  }while(1)
 
  trafficSignal.lightStat = 'off'
}
 
 
turnOnTraffic()
 
onoffButton.onclick = function(){
  if(trafficSignal.lightStat === 'off'){
    turnOnTraffic()
    onoffButton.innerHTML = '关闭'
  } else {
    onoffButton.innerHTML = '开启'
    trafficSignal.cancel()
  }
}

大家对代码实行局地改进,封装三个 TrafficSignal,让 onoffButton 只控制traficSignal 的情景。这里我们用一个简便的 Signal 库,它能够兑现景况和调节流的分手,举例:

JS Bin on jsbin.com

const signal = new Signal('default') ;(async () => { await signal.while('default') console.log('leave default state') })() ;(async () => { await signal.until('state1') console.log('to state1') })() ;(async () => { await signal.until('state2') console.log('to state2') })() ;(async () => { await signal.until('state3') console.log('to state3') })() setTimeout(() => { signal.state = 'state0' }, 1000) setTimeout(() => { signal.state = 'state1' }, 2000) setTimeout(() => { signal.state = 'state2' }, 3000) setTimeout(() => { signal.state = 'state3' }, 4000)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const signal = new Signal('default')
 
;(async () => {
    await signal.while('default')
    console.log('leave default state')
})()
 
;(async () => {
    await signal.until('state1')
    console.log('to state1')
})()
 
;(async () => {
    await signal.until('state2')
    console.log('to state2')
})()
 
;(async () => {
    await signal.until('state3')
    console.log('to state3')
})()
 
setTimeout(() => {
    signal.state = 'state0'
}, 1000)
 
setTimeout(() => {
    signal.state = 'state1'
}, 2000)
 
setTimeout(() => {
    signal.state = 'state2'
}, 3000)
 
setTimeout(() => {
    signal.state = 'state3'
}, 4000)

有同学说,那样写代码也不轻易啊,代码量比地点写法还要多。的确那样写代码量是超多的,不过它布局清晰,耦合度低,可以超级轻易扩张,比方:

JS Bin on jsbin.com

class Idle extends Signal { async wait(time){ this.state = 'wait' const timer = setTimeout(() => { this.state = 'timeout' }, time) await this.while('wait') clearTimeout(timer) } cancel(){ this.state = 'cancel' } } class TrafficSignal extends Signal { constructor(id){ super('off') this.container = document.getElementById(id) this.idle = new Idle() } get lightStat(){ return this.state } async pushStat(val, dur = 0){ this.container.className = val this.state = val if(dur) await this.idle.wait(dur) } get canceled(){ return this.idle.state === 'cancel' } cancel(){ this.idle.cancel() this.pushStat('off') } } const trafficSignal = new TrafficSignal('traffic') async function turnOnTraffic(){ //noprotect do { await trafficSignal.pushStat('stop', 1000) if(trafficSignal.canceled) break await trafficSignal.pushStat('pass', 1500) if(trafficSignal.canceled) break await trafficSignal.pushStat('wait', 500) if(trafficSignal.canceled) break }while(1) trafficSignal.lightStat = 'off' } turnOnTraffic() onoffButton.onclick = function(){ if(trafficSignal.lightStat === 'off'){ turnOnTraffic() onoffButton.innerHTML = '关闭' } else { onoffButton.innerHTML = '开启' trafficSignal.cancel() } } turnRed.onclick = function(){ trafficSignal.cancel() trafficSignal.pushStat('stop') } turnGreen.onclick = function(){ trafficSignal.cancel() trafficSignal.pushStat('pass') } turnYellow.onclick = function(){ trafficSignal.cancel() trafficSignal.pushStat('wait') }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
class Idle extends Signal {
  async wait(time){
    this.state = 'wait'
    const timer = setTimeout(() => {
      this.state = 'timeout'
    }, time)
    await this.while('wait')
    clearTimeout(timer)
  }
  cancel(){
    this.state = 'cancel'
  }
}
 
class TrafficSignal extends Signal {
  constructor(id){
    super('off')
    this.container = document.getElementById(id)
    this.idle = new Idle()
  }
  get lightStat(){
    return this.state
  }
  async pushStat(val, dur = 0){
    this.container.className = val
    this.state = val
    if(dur) await this.idle.wait(dur)
  }
  get canceled(){
    return this.idle.state === 'cancel'
  }
  cancel(){
    this.idle.cancel()
    this.pushStat('off')
  }
}
 
const trafficSignal = new TrafficSignal('traffic')
 
async function turnOnTraffic(){
  //noprotect
  do {
    await trafficSignal.pushStat('stop', 1000)
    if(trafficSignal.canceled) break
    await trafficSignal.pushStat('pass', 1500)
    if(trafficSignal.canceled) break
    await trafficSignal.pushStat('wait', 500)
    if(trafficSignal.canceled) break
  }while(1)
 
  trafficSignal.lightStat = 'off'
}
 
 
turnOnTraffic()
 
onoffButton.onclick = function(){
  if(trafficSignal.lightStat === 'off'){
    turnOnTraffic()
    onoffButton.innerHTML = '关闭'
  } else {
    onoffButton.innerHTML = '开启'
    trafficSignal.cancel()
  }
}
 
turnRed.onclick = function(){
  trafficSignal.cancel()
  trafficSignal.pushStat('stop')
}
 
turnGreen.onclick = function(){
  trafficSignal.cancel()
  trafficSignal.pushStat('pass')
}
 
turnYellow.onclick = function(){
  trafficSignal.cancel()
  trafficSignal.pushStat('wait')
}

Signal 特别相符于事件调整的场子,再举三个更简便易行的例证,假设我们用一个按键调整轻便的动漫片的脚刹踏板和实行,能够这么写:

JS Bin on jsbin.com

let traffic = new Signal('stop') requestAnimationFrame(async function update(t){ await traffic.until('pass') block.style.left = parseInt(block.style.left || 50) 1 'px' requestAnimationFrame(update) }) button.onclick = e => { traffic.state = button.className = button.className === 'stop' ? 'pass' : 'stop' }

1
2
3
4
5
6
7
8
9
10
11
let traffic = new Signal('stop')
 
requestAnimationFrame(async function update(t){
  await traffic.until('pass')
  block.style.left = parseInt(block.style.left || 50) 1 'px'
  requestAnimationFrame(update)
})
 
button.onclick = e => {
  traffic.state = button.className = button.className === 'stop' ? 'pass' : 'stop'
}

javascript 四线程异步队列

第风流浪漫,你得掌握 jQuery.Deferred 的光景用法,然后,我们进去正题吧:

 

库代码:

 

复制代码

/*!

 * 多线程异步队列

 * 信赖 jQuery 1.8 (如若您用的是 1.6或1.7, 只要将源码中的 then方法替换为pipe方法 就可以卡塔尔(قطر‎

 */

 

/**

 * @n {Number} 正整数, 线程数量

 */

function Queue (n) {

    n = parseInt(n || 1, 10);

    return (n && n > 0) ? new Queue.prototype.init(n) : null;

}

 

Queue.prototype = {

    init: function (n) {

        this.threads = [];

        this.taskList = [];

 

        while (n--) {

            this.threads.push(new this.Thread)

        }

    },

 

    /**

     * @callback {Fucntion} promise对象done时的回调函数,它的再次来到值必得是三个promise对象

     */

    push: function (callback) {

        if (typeof callback !== 'function') return;

 

        var index = this.indexOfIdle();

 

        if (index != -1) {

            this.threads[index].idle(callback)

            try { console.log('Thread-' (index 1) ' accept the task!') } catch (e) {}

        }

        else {

            this.taskList.push(callback);

 

            for (var i = 0, l = this.threads.length; i < l; i ) {

 

                (function(thread, self, id){

                    thread.idle(function(){

                        if (self.taskList.length > 0) {

                            try { console.log('Thread-' (id 1) ' accept the task!') } catch (e) {}

 

                            var promise = self.taskList.pop(卡塔尔(英语:State of Qatar)(卡塔尔(قطر‎;    // 准确的重返值应该是多少个promise对象

                            return promise.promise ? promise : thread.promise;

                        } else {

                            return thread.promise

                        }

                    })

                })(this.threads[i], this, i);

 

            }

        }

    },

    indexOfIdle: function () {

        var threads = this.threads,

            thread = null,

            index = -1;

 

        for (var i = 0, l = threads.length; i < l; i ) {

            thread = threads[i];

 

            if (thread.promise.state() === 'resolved') {

                index = i;

                break;

            }

        }

 

        return index;

pc28.am神测网,    },

    Thread: function () {

        this.promise = $.Deferred().resolve().promise();

 

        this.idle = function (callback) {

            this.promise = this.promise.then(callback)

        }

    }

};

 

Queue.prototype.init.prototype = Queue.prototype;

复制代码

使用示例:

 

复制代码

    var queue = new Queue(3卡塔尔国;    // 创立一个负有3个线程的种类

 

  // task-1

    queue.push(function(){

        var defer = $.Deferred();

 

        setTimeout(function(){

            defer.resolve()

        }, 8000);

 

        return defer.promise()

    })

 

  // task-2

    queue.push(function(){

        var defer = $.Deferred();

 

        setTimeout(function(){

            defer.resolve()

        }, 2000);

 

        return defer.promise()

    })

 

  // task-3

    queue.push(function(){

        var defer = $.Deferred();

 

        setTimeout(function(){

            defer.resolve()

        }, 6000);

 

        return defer.promise()

    })

 

  // task-4

    queue.push(function(){

        var defer = $.Deferred();

 

        setTimeout(function(){

            defer.resolve()

        }, 3000);

 

        return defer.promise()

    })

 

  // task-5

    queue.push(function(){

        var defer = $.Deferred();

 

        setTimeout(function(){

            defer.resolve()

        }, 2000);

 

        return defer.promise()

    })

 

  // task-6

    queue.push(function(){

        var defer = $.Deferred();

 

        setTimeout(function(){

            defer.resolve()

        }, 2000);

 

        return defer.promise()

    })

复制代码

调节台有突显 queue.push的 function (暂时叫它task卡塔尔  最终是哪位进程管理的

 

实例化后,队列里的3个线程都是高居空闲状态的

将task-1分配给线程1, 那个职务耗费时间 8s

将task-2分配给线程2, 那个职分耗费时间 2s

将task-3分配给线程3, 那么些职责耗费时间 6s

 

因为脚下未曾空余进程,队列之中则将task-4、task-5、task-6增添到等候区

 

因为task-2耗时2s,进度2最早被解放,然后task-4就被分配到进程2去处理,由此及彼,最终调节台展现的长河使用意况是:1、2、3、2、2、3

 

 

 

本条库的选择处境是那般的

1、如本人前段时间做的等级次序:

主播在做直播,超多客官会给主播送礼物,这一个礼品都以有js动漫特效的,页面中最多可以何况出示多少个礼物特效

 

2、互相重视的异步要求

a须要重视b伏乞,b央浼重视c恳求,c央求看重。。。

这些必要大家就足以应用这一个库那样完成:

 

复制代码

var queue = new Queue(1);

 

// request c

queue.push(function(){

    return $.ajax(卡塔尔国;    // jq 的ajax重临的难为 promise对象

})

 

// request b

queue.push(function(){

    return $.ajax();

})

 

// request a

queue.push(function(){

    return $.ajax();

})

复制代码

 queue.push(callback卡塔尔   callback必需回到贰个promise对象

 

多线程异步队列 首先,你得精晓jQuery.Deferred 的大约用法,然后,大家进去正题吧: 库代码: 复制代码 /*! * 十二线程异步队列 * 依...

CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link href="style/style.css" rel="stylesheet" type="text/css">
<script language="JavaScript">
var state;
//初始化
function playerinit()
{
player.url="mp3.m3u";
player.settings.autoStart = false ;
}
//播放
function play()
{
if (player.controls.isavailable('play'))
{
player.controls.play();
state=setInterval("updatetime()",1000);
playerinfo.innerHTML = "播放";
}
}
//暂停
function pause()
{
if (player.controls.isavailable('pause'))
{
player.controls.pause();
clearInterval(state);
playerinfo.innerHTML = "暂停";
}
}
//停止
function stop()
{
if (player.controls.isavailable('stop'))
{
player.controls.stop();
clearInterval(state);
playerinfo.innerHTML = "停止";
}
}
//前首
function previous()
{
if (player.controls.isavailable( 'previous' ))
{
player.controls.previous();
playerinfo.innerHTML = "前一首";
}
}
//后首
function next()
{
if (player.controls.isavailable( 'next' ))
{
player.controls.next();
playerinfo.innerHTML = "下一首";
}
}
//?
function step()
{
if (player.controls.isavailable( 'step' ))
player.controls.step( 1 );
}
//音量-
function voldown()
{
if ( player.settings.volume < 5 )
{
player.settings.volume = 0;
playerinfo.innerHTML = "0";
}
else
{
player.settings.volume -= 5;
playerinfo.innerHTML = player.settings.volume;
}
}
//音量
function volup()
{
if ( player.settings.volume > 95 )
{
player.settings.volume = 100;
playerinfo.innerHTML = "100";
}
else
{
player.settings.volume = 5;
playerinfo.innerHTML = player.settings.volume;
}
}
//静音
function mute()
{
player.settings.mute = !player.settings.mute;
}
//声道
function balance()
{
switch (player.settings.balance)
{
case 0:
   player.settings.balance = 100;
   playerinfo.innerHTML = '左声道';
   break;
case 100:
   player.settings.balance = -100;
   playerinfo.innerHTML = '右声道';
   break;
case -100:
   player.settings.balance = 0;
   playerinfo.innerHTML = '全声道';
   break;
default :
   player.settings.balance = 0;
   playerinfo.innerHTML = '全声道';
   break;
}
}
//更新时间
function updatetime()
{
playerinfo.innerHTML = player.controls.currentPositionString " | " player.currentMedia.durationString;
}
</script>
</head>
<body onload="playerinit();">
<table width="300">
<tr>
    <td><object id="player" classid="CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6" type="application/x-oleobject" width="300" height="60">
      <param name="autoStart" value="false">
      <param name="balance" value="0">
      <param name="currentPosition" value="0">
      <param name="currentMarker" value="0">
      <param name="enableContextMenu" value="true">
      <param name="enableErrorDialogs" value="false">
      <param name="enabled" value="true">
      <param name="fullScreen" value="false">
      <param name="invokeURLs" value="false">
      <param name="mute" value="true">
      <param name="playCount" value="1">
      <param name="rate" value="1">
      <param name="uiMode" value="none">
      <param name="volume" value="100">
    </object></td>
</tr>
<tr>
    <td><span id="playerinfo"></span></td>
</tr>
<tr>
    <td>
      <div align="center">
<input type="button" class="but11" onmouseover=this.className="but12"; onmouseout=this.className="but11"; name="previous" title="上一首" onclick="previous();">
<input type="button" class="but21" onmouseover=this.className="but22"; onmouseout=this.className="but21"; name="play" title="播放" onclick="play();">
<input type="button" class="but31" onmouseover=this.className="but32"; onmouseout=this.className="but31"; name="pause" title="暂停" onclick="pause();">
<input type="button" class="but41" onmouseover=this.className="but42"; onmouseout=this.className="but41"; name="stop" title="停止" onclick="stop();">
<input type="button" class="but51" onmouseover=this.className="but52"; onmouseout=this.className="but51"; name="next" title="下一首" onclick="next();">
<input type="button" class="but61" onmouseover=this.className="but62"; onmouseout=this.className="but61"; name="voldown" title="音量-" onclick="voldown();">
<input type="button" class="but61" onmouseover=this.className="but62"; onmouseout=this.className="but61"; name="volup" title="音量 " onclick="volup();">
<input type="button" class="but61" onmouseover=this.className="but62"; onmouseout=this.className="but61"; name="mute" title="静音" onclick="mute();">
<input type="button" class="but61" onmouseover=this.className="but62"; onmouseout=this.className="but61"; name="balance" title="声道" onclick="balance();">
   </div>
</td>
</tr>
</table>
<script language = "JavaScript" for = player event = playstatechange(newstate)>
switch (newstate){
case 1:
   playerinfo.innerHTML = "停止";
   break;
case 2:
   playerinfo.innerHTML = "暂停";
   break;
case 3:
   playerinfo.innerHTML = "正在播放";
   break;
case 4:
   playerinfo.innerHTML = "4";
   break;
case 5:
   playerinfo.innerHTML = "5";
   break;
case 6:
   playerinfo.innerHTML = "正在缓冲...";
   break;
case 7:
   playerinfo.innerHTML = "7";
   break;
case 8:
   playerinfo.innerHTML = "8";
   break;
case 9:
   playerinfo.innerHTML = "正在连接...";
   break;
case 10:
   playerinfo.innerHTML = "寻思妥贴。招待光降<a href=';";
   break;
case 11:
   playerinfo.innerHTML = "11";
   break;
default:
   playerinfo.innerHTML = "";
}
</script>
</body>
</html>

总结

咱俩得以用 Signal 来支配异步流程,它最大的效果与利益是将状态和操纵抽离,大家只要求转移 Signal 的景色,就可以决定异步流程,Signal 扶持 until 和 while 谓词,来决定景况的改进。

可以在 GitHub repo 上进一层通晓有关 Signal 的详细音信。

1 赞 收藏 评论

pc28.am神测网 2

本文由pc28.am发布于前端技术,转载请注明出处:用功率信号来支配异步流程,web播放控件

上一篇:CSS3逐帧动漫,深远精晓CSS3 下一篇:没有了
猜你喜欢
热门排行
精彩图文