Revisited = image.onload НЕ вызывается

Очень старая, но очень ООН решаемая тема: image.onload не называется.

Код рассказывает историю лучше, чем слова...

Вызов.html =

<script>
var newConnection = new MeasureConnectionSpeed();

if (newConnection.isHighSpeed())
    doSomething1;
else
    doSomething2;
</script>

Называется.html =

<script>
function MeasureConnectionSpeed() {

    var connection = this;

    var imgDownloadSrc = "http://someLargeImage.jpg"; 
    var imgDownloadSize = 943 * 1024;     // bytes

    var startTime = 0,
        endTime   = 0;   // set later
    connection.isHighSpeedConnection = false;   // = a Object Property

    // an Object Method ...
    // just the function declaration which is called via
    // connection.computeResults()
    connection.isHighSpeed    = isHighSpeed;

    connection.computeResults = computeResults;   // another Object Method

    var testImgDownload = new Image();

    testImgDownload.onload = function () {

        endTime = (new Date()).getTime();

        connection.computeResults();

    }   // testImgDownload.onload


    testImgDownload.onerror = function (err, msg) {

        alert("Invalid image, or error downloading");

    }

    // We immediately continue while testImgDownload is still loading ...

    // the timer is started here and ended inside testImgDownload.onload 
    startTime = (new Date()).getTime();

    // This forces an attempt to download the testImgDownload and get the
    // measurements withOUT actually downloading to your Cache:
    var cacheBuster = "?nnn=" + startTime;
    testImgDownload.src = imgDownloadSrc + cacheBuster;


    function computeResults() {

        var speedMbps  = someNumber;

        connection.isHighSpeedConnection = speedMbps > 20;

    }   // computeResults

    // this.isHighSpeed() = isHighSpeed()
    function isHighSpeed() {

        return connection.isHighSpeedConnection;

    }

}   // MeasureConnectionSpeed

</script>

* РЕДАКТИРОВАТЬ #1 *

Еще два бита...

Я решил скачать Google Chrome и локально протестировать мой.html. Chrome получил доступ к обработчику событий.onerror моего исходного кода. Safari и Firefox никогда не делали???

Еще одно любопытное наблюдение... используя Chrome, alert(err) внутри моего обработчика событий.onerror выдается "undefined". Но я использовал alert(this.width) а также alert(this.naturalWidth), каждый показывает 0... что означает, что это недопустимое изображение???

И ошибка недействительного изображения даже происходит, если я помещаю src перед .onload Handler.

Это действительно так сейчас!

* РЕДАКТИРОВАТЬ № 2 - 8 августа 2015 года *

1) Мне правда очень жаль, что я не вернулся раньше... но я начал плохо себя чувствовать, поэтому получил немного больше физического отдыха

2) Так или иначе, я реализовал замечательный код IIFE Дэйва Снайдера, и он определенно работал... код в.onload Handler работал правильно, и я действительно чрезвычайно благодарен Дейву и все время, которое он предоставил little-ole-me. Конечно, я сбросил newConnection = new MeasureConnectionSpeed ​​() и использовал подход Дейва IIFE.

Теперь все, что мне нужно выяснить, почему этот код дает мне скорость около 5 Мбит / с, где у меня 30 Мбит / с через Ethernet-маршрутизатор. Я действительно ожидал бы увидеть число близко.

Я действительно, очень не хочу включать другой API, так как моя цель измерения скорости состоит в том, чтобы выбрать погоду для перенаправления на относительно "загруженный" сайт или "упрощенную" версию.

Большое спасибо, Дейв. Ты мой герой.

Джон Лав

1 ответ

Решение

Это работает для меня в Chrome.

(function(){
  var imgDownloadSrc = "https://upload.wikimedia.org/wikipedia/commons/d/d8/Schwalbenschwanz_%28Papilio_machaon%29.jpg",
      testImgDownload = new Image(),
      startTime, endTime,
      stackOverflowLog = document.getElementById('log');

  var log = function(message, str) {
    stackOverflowLog.innerHTML += message.replace("%s", str) + "<br>";
    console.log(message, str);
  }

  testImgDownload.onload = function () {
    log('image loaded!');
    endTime = +new Date();
    log('end time: %s', startTime);
    log('total time: %s', (endTime - startTime));
  }

  testImgDownload.onerror = function (err, msg) {
    throw "Invalid image, or error downloading";
  }

  startTime = +new Date();
  log('start time: %s', startTime);
  testImgDownload.src = imgDownloadSrc + "?" + startTime;
  log('downloading: %s', testImgDownload.src);
})();
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Untitled Document</title>
</head>

<body>
   <pre id="log"></pre>
</body>
</html>

Вот ваш код, слегка модифицированный, чтобы он работал. image.onload вроде нормально работает, но isHighSpeed() вызывается до завершения загрузки изображения. Он должен быть реорганизован / переупорядочен, чтобы вы могли позвонить isHighSpeed() после того, как это было установлено. Для такого рода вещей часто используется обратный вызов.

/* for illustration */
var stackOverflowLog = document.getElementById("log");
var log = function(message, str) {
  stackOverflowLog.innerHTML += message.replace("%s", str) + "<br>";
  console.log(message, str);
}


/* calling.html */

var newConnection = new MeasureConnectionSpeed();

log('newConnection.isHighSpeed()? %s', newConnection.isHighSpeed());

/* called.html */

function MeasureConnectionSpeed() {

    var connection = this;

    var imgDownloadSrc = "https://upload.wikimedia.org/wikipedia/commons/d/d8/Schwalbenschwanz_%28Papilio_machaon%29.jpg"; 
    var imgDownloadSize = 1709360 * 8;     // bits (~1.6mb * 8)

    var startTime = 0,
        endTime   = 0;   // set later
    connection.isHighSpeedConnection = undefined;   // = a Object Property

    // an Object Method ...
    // just the function declaration which is called via
    // connection.computeResults()
    connection.isHighSpeed    = isHighSpeed;

    connection.computeResults = computeResults;   // another Object Method

    var testImgDownload = new Image();

    testImgDownload.onload = function () {

        endTime = (new Date()).getTime();

        log('endTime: %s', endTime);
      
        connection.computeResults();

    }   // testImgDownload.onload


    testImgDownload.onerror = function (err, msg) {

        log("!!! ERROR Invalid image, or error downloading");

    }

    // We immediately continue while testImgDownload is still loading ...

    // the timer is started here and ended inside testImgDownload.onload 
    startTime = (new Date()).getTime();

    log('startTime: %s', startTime);
  
    // This forces an attempt to download the testImgDownload and get the
    // measurements withOUT actually downloading to your Cache:
    var cacheBuster = "?nnn=" + startTime;
    testImgDownload.src = imgDownloadSrc + cacheBuster;

    log('loading: %s', testImgDownload.src);

    function computeResults() {
        var duration, speed, speedMbps;
      
        duration = (endTime - startTime) / 1000; // seconds 
        speed = imgDownloadSize / duration; // bits per second
        speedMbps = speed / 1000000; // megabits

        log('duration: %s', duration);
        log('speed: %s', speed);
        log('speedMbps: %s', speedMbps);
      
        connection.isHighSpeedConnection = speedMbps > 20;

    }   // computeResults

    // this.isHighSpeed() = isHighSpeed()
    function isHighSpeed() {

        return connection.isHighSpeedConnection;

    }

}   // MeasureConnectionSpeed
<pre id="log"></pre>

Другие вопросы по тегам